Link to home
Start Free TrialLog in
Avatar of AWestEng
AWestEngFlag for Sweden

asked on

RemoveHandler problem

Hi

Here I have some pseudocode that shows an example of my handler problem.

1: I have a process with an exit handler
2: In another methods I remove the handler and kill the process

Problem:
When killing the process the exit methods is still executing, so the removehandler dosen't seem to work. any tips here?

Thx
Private Property LaunchedProcesses() As Hashtable
    Get
        Return m_serverProcess
    End Get
    Set(ByVal Value As Hashtable)
        m_serverProcess = Value
    End Set
End Property
 
Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs)
End Sub
 
Private Sub M1 
  Dim myProcss as Process
  
  -'''''''' Some code
  
  '// Add process exited handler 
  AddHandler myProcess.Exited, AddressOf myProcess_Exited
  
  myProcss.Start
  
  Me.LaunchedProcesses.Add("p1",myProcss) 
End Sub
 
Private Sub M2
 
'// Get process
shutDownProcess = DirectCast(Me.LaunchedProcesses.Item("p1"), Process)
 
'// Remove process exited handler
RemoveHandler shutDownProcess.Exited, AddressOf myProcess_Exited
 
shutDownProcess.Kill 
End Sub

Open in new window

Avatar of SStory
SStory
Flag of United States of America image

Maybe when you shut it down, you should get it, and then remove it from the collection to avoid the extra reference. I don't know if this is the problem, but it is the first thing that grabbed me.

Another thought is... is there not a more graceful way to exit the process instead of .kill?

Maybe the kill happens before the removehandler finishes processing.  

See if removing it from the collection first works.
Avatar of AWestEng

ASKER

This is just some pseudocode to describe the problem. so kill is just to show want I need help with
1> First I execute the M1, the process start with a handler and I add it to the property.
2> Then I run M2, I get the process from the property, and removes the handler from M1
3> I now add a new handler to that process and then I kill it.
The new handler dosen't work instead the old handler still executes
I have also tried to remove the process from the property as soon as I get it but that did not help, still the same problem.
I think we are going to need some actual code to spot the problem...
I'm sure what you said is clear to you but it is very vague to the rest of us.

How do you add a handler to a property. From what you gave me it looks like you add a handler to an object that then goes into a class.  I just thought maybe by still having it in the class you still had a reference to the object and that might be causing you grief.

Like Idle_Mind said, we need some real code to know what you want to do and are doing wrong.
Here is some "better" code (I hope) to explaine it
    Private m_serverProcess As New Hashtable
    Private Property LaunchedProcesses() As Hashtable
        Get
            Return m_serverProcess
        End Get
        Set(ByVal Value As Hashtable)
            m_serverProcess = Value
        End Set
    End Property
 
    Private Sub Start(ByVal applicationPath As String)
        Dim myProcess As Process
 
        Dim server As String = String.Empty
        Dim foundProcess As Boolean = False
 
        '// Lookup the real server name
        server = m_serverListNames.Item(m_activeServer)
 
        '// Create a new process
        myProcess = New Process()
 
        '// Set process settings
        With myProcess.StartInfo
            .FileName = applicationPath & server & ".exe"
            .Arguments() = "/input=True,True"
            .CreateNoWindow = False
            .ErrorDialog = False
            .UseShellExecute = False
            .RedirectStandardOutput = True
            .RedirectStandardInput = True
            .RedirectStandardError = True
            .WindowStyle = ProcessWindowStyle.Normal
        End With
 
        '// Enable events
        myProcess.EnableRaisingEvents = True
 
        '// Add process exited handler
        AddHandler myProcess.Exited, AddressOf myProcess_Exited
 
        '// Start process
        myProcess.Start()
 
        If Not myProcess.Responding Then
            myProcess.Kill()
        Else
            Me.LaunchedProcesses.Add(server, myProcess)
        End If
    End Sub
 
    Private Sub [Stop](ByVal applicationPath As String)
        Dim shutDownProcess As Process
 
        Dim server As String = String.Empty
        Dim foundProcess As Boolean = False
 
        '// Lookup the real server name
        server = m_serverListNames.Item(m_activeServer)
 
        '// Get process
        shutDownProcess = TryCast(Me.LaunchedProcesses.Item(server), Process)
 
        '// Set process parameters for a controlled shutdown
        shutDownProcess.StartInfo.Arguments() = "/shutdown"
 
        '// Remove process exited handler from startup process
        RemoveHandler shutDownProcess.Exited, AddressOf myProcess_Exited
 
        '// Add process exited handler for shutdown process
        AddHandler shutDownProcess.Exited, AddressOf m_shutDownProcess_Exited
 
        '// Start process
        shutDownProcess.Start()
 
        If Not shutDownProcess.Responding Then
            shutDownProcess.Kill()
        Else
            Me.LaunchedProcesses.Remove(server)
        End If
 
    End Sub
 
    Private Sub myProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs)
        If Me.InvokeRequired Then
            Me.Invoke(New ProcessExited(AddressOf myProcess_Exited), New Object() {sender, e})
        Else
            MessageBox.Show("Test1")
        End If
    End Sub
 
    Private Sub m_shutDownProcess_Exited(ByVal sender As Object, ByVal e As System.EventArgs)
        If Me.InvokeRequired Then
            Me.Invoke(New ProcessExited(AddressOf myProcess_Exited), New Object() {sender, e})
        Else
            MessageBox.Show("Test2")
        End If
    End Sub

Open in new window

When I execute the stop method, the myProcess_Exited is executeed when the process is exited.
But is should be the m_shutDownProcess_Exited methods
 So I must do something wrong :)
It looks like to me that you create a process and add it to a collection along with the server name.

Then to stop it you get a handle to it (object ref), but you don't remove it from the collection which leaves a reference still there, then to stop it, you start it again which creates another process.

This seems really strange to me.

See this link:
http://www.thescarms.com/dotnet/Process.aspx

I guess you know that the way you are launching it, it doesn't wait for the process.
So it seems the
      If Not myProcess.Responding Then
              myProcess.Kill()
code may not get processed at the right time.  I'm just saying the process could take a while to start and this code may never get executed.

I assume the processes being launched aren't ones that you have written.  Is that true?

.Close or CloseMainWindow might be better methods to use to stop the process instead of kill.



See code below.

If none of this works, then I am not sure why.


       '// Get process
        shutDownProcess = TryCast(Me.LaunchedProcesses.Item(server), Process)
 
        '// Remove process from collection
        Me.LaunchedProcesses.Remove(shutdownProcess)
 
        '// Remove process exited handler from startup process
        RemoveHandler shutDownProcess.Exited, AddressOf myProcess_Exited

Open in new window

In my application I use

Private Sub MyApplication_StartupNextInstance(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
End Sub
To pass parameters to the instance, so thats way I start it again but with another argument.
This is the main path
1. I start the process,
2. I add it to a collection
3. I get process from the collection
4. I stop the process
In the stop method I want to change handler of the process object.  
In the start methods it points to the method "myProcess_Exited" but when stopping it I want to remove that one and repoint it to another method , this one "m_shutDownProcess_Exited"

so the problem is that in some way I don't manage to remove the pointer/handler to "myProcess_Exited", because when the process exited it still execute the "myProcess_Exited" method, and as you can see in the code I have removed it when I'm in the Stop method

Isn't this:
 '// Start process
        shutDownProcess.Start()

starting a brand new process even though you never got rid of the old one?

so if you kill handlers from it in the STOP method and then try to restart a new process and it fails
    If Not shutDownProcess.Responding Then
            'this does not remove the old process from the collection event though the handlers to it
            'have been removed
            'Is that what you wanted?
            shutDownProcess.Kill()
        Else
            'this does finally remove it from the collection
            Me.LaunchedProcesses.Remove(server)
        End If
ASKER CERTIFIED SOLUTION
Avatar of SStory
SStory
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
"starting a brand new process even though you never got rid of the old one? "
No it does not, if you use the internal framwork and MyApplication_StartupNextInstance in Application event it will not do that, it will execute the same instance again and I can get the argument passed thru the new process start. works great.. So it's the same instance as before,
 
The kill part code is not the problem here, even if I kill it from Task Manager it still execute the old handler and not the new one. And if I remove it I can't undertand wy this event is executing
AWestEng,

Thanks for the information.  I'm sorry I don't know why it isn't working either.
Yes this sems to be the problem
"Hi, I think I understand why it behaves how it behaves.
A new feature of VB9 allows you to AddHandler for methods with slightly
different signatures than signature of event is. However as I understand it
some hidden routing method/delegate (which routes event to method with
different signature) is created in compile time. And when you uses
RemoveHandler another one is created which results to RemoveHandler removing
handler which had been never attached. So, nothing happens and handler
attached via AddHanlder is still attached.
There are two ways how to prevent this behavior:
1) Is prior VB9 - ensure that method (handler) as EXACTLY same signature as
event (event delegate)
2) Add handler is some way like this
Dim HadlerDelegate = AddressOf MyMethod
AddHandler TheObject.Event, HandlerDelegate
then store HandlerDelegate somewhere and use it with RemoveHandler."
 
Thx m8

 
Good work!! Thx :)