开发者

Dispose and/or Finalize not called when using VB6 IDE END Debugging

开发者 https://www.devze.com 2023-03-09 09:50 出处:网络
Following on from my question a little while ago. I have resolved most of the parts related to that. Detect when a COM Object goes out of Scope

Following on from my question a little while ago.

I have resolved most of the parts related to that. Detect when a COM Object goes out of Scope

I now face a new problem whilst developers are working on the VB6 code. If they run the project inside the IDE, and then press END, the Dispose nor Finalize are being called. It's like the Debugging part of VB6 just detaches immediately without calling disposes etc.

I have tested this via using the standard application close and Finalize gets called from COM -> .NET component and my thread shuts down, but if the End button is pressed there is no Finalise, no Dispose and my thread just keeps running.

Inside my component I tried this

bool debuggerAttachedatStart = System.Diagnostics.Debugger.IsAttached;
System.Windows.Forms.MessageBox.Show("The Debugger is currently -" + debuggerAttachedatStart);

but when you run it within VB6, it's always False.

I got out Process Explorer and had a look at VB6 and I noticed it creates an Event object upon startup of the Debugging session开发者_运维问答, but it is a unique guid each time you start. (\Sessions\1\BaseNamedObjects{70FAF0B5-A76B-4C6A-92BE-5201B2335871})

Just wondering if there is anything I can do so that I can gracefully detect that the Debugging has stopped (or started) within VB6.


No, there is nothing you can do. Stopping debugging does not give your program a chance to run code.


I believe I may have found a solution and thought I'd share it, incase someone has a better idea for how I can gracefully perform the shutdown of my thread.

In my .NET assembly add another Event definition

<InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(Manager.EventsId)> _
Public Interface IManagerEvents
    'Others Removed
    <DispId(4)> Sub HostAlive(ByRef alive As Boolean)
End Interface

and in the Code Definition add Public Delegate Sub HostAliveDelegate(ByRef state As Boolean)

Now in the main area of Code, because we will be talking to VB6 we need to be on the correct thread, so grab a SyncContext. And setup the threads.

public sub New()
    Dim operation As ComponentModel.AsyncOperation
    operation = AsyncOperationManager.CreateOperation(Nothing)
    mSync = AsyncOperationManager.SynchronizationContext
    operation.OperationCompleted()
    'setup thread work.....
end sub 

Private Sub ConnectPipe()
    Dim lastAliveCheck As DateTime
    lastAliveCheck = DateTime.Now.AddSeconds(2)
    While Not mRunningEvent.Wait(0)


      'do all the work to prepar and setup the PIPE.
      'if we successfully connect
        Using NoOpTimer As New Threading.Timer(New Threading.TimerCallback(AddressOf TimerTicks), mPipe, 2000, 2000)
            'If we disconnect, this Event gets allowing the exit and reconnect to commence
            mConnectedHold.WaitOne()
        End Using

        'we must have not connected so ensure that we are still inside a running process
            PipeLog.Write("Attempting reconnect to named pipe")
            mConnectedStopper.Wait(500)
            If DateTime.Now > lastAliveCheck Then
                lastAliveCheck = DateTime.Now.AddSeconds(2)
                Dim e As New HostAliveEventArgs()
                OnHostAlive(e)
                If Not e.IsAlive Then
                    'The host did not set the event. Make sure the event is wired up and setting the value to true.
                    Exit While
                End If
            End If
    End While
    DisposePipe
    mExitingEvent.Set()
End Sub       

Protected Sub OnHostAlive(ByVal e As HostAliveEventArgs)
    mSync.Send(AddressOf OnHostAliveContextPost, e)
End Sub

Private Sub OnHostAliveContextPost(ByVal state As Object)
    Dim e As HostAliveEventArgs = CType(state, HostAliveEventArgs)
    RaiseEvent HostAlive(e.IsAlive)
End Sub   

Over inside our VB6 class that utilises this component.

Private WithEvents comm As IPSClient_Intercommunication.Manager

Private Sub Class_Initialize()
    Set comm = New IPSClient_Intercommunication.Manager
End Sub

Private Sub comm_HostAlive(ByRef alive As Boolean)
    alive = True
End Sub

What I discovered is that even if you use a CustomEvent it is always bound, so you can't just determine that there are no connected event delegates and disconnect. When you raise the event if the host application has been shutdown, then the event doesn't set the alive to true, and you can assume that it's been aborted.

0

精彩评论

暂无评论...
验证码 换一张
取 消