Утилизация и / или финализация не вызывается при использовании отладки VB6 IDE END - PullRequest
0 голосов
/ 01 июня 2011

Исходя из моего вопроса некоторое время назад.

Я решил большинство частей, связанных с этим. Обнаружение, когда COM-объект выходит из области видимости.

Теперь я столкнулся с новой проблемой, пока разработчики работают над кодом VB6. Если они запускают проект внутри IDE, а затем нажимают END, вызываются Dispose или Finalize. Это похоже на то, что отладочная часть VB6 просто отключается сразу, без вызова утилизации и т. Д.

Я проверил это с помощью стандартного закрытия приложения, и Finalize вызывается из компонента COM -> .NET, и мой поток закрывается, но если нажата кнопка «Конец», то нет «Завершить», нет «Dispose», и мой поток просто продолжает работать .

Внутри моего компонента я попробовал это

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

но когда вы запускаете его в VB6, оно всегда ложно.

Я вышел из Process Explorer и взглянул на VB6, и заметил, что он создает объект Event при запуске сеанса отладки, но это уникальный гид при каждом запуске. (\ \ Сессии 1 \ BaseNamedObjects {70FAF0B5-A76B-4C6A-92BE-5201B2335871})

Просто интересно, могу ли я что-нибудь сделать, чтобы я мог изящно определить, что отладка остановлена ​​(или запущена) в VB6.

Ответы [ 2 ]

3 голосов
/ 01 июня 2011

Нет, вы ничего не можете сделать. Остановка отладки не дает вашей программе возможности выполнить код.

0 голосов
/ 03 июня 2011

Я думаю, что, возможно, нашел решение и подумал, что поделюсь им, если у кого-то есть идея, как я могу изящно выполнить отключение моего потока.

В моей сборке .NET добавьте еще одно определение события

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

и в определении кода добавить Открытый делегат Sub HostAliveDelegate (состояние ByRef As Boolean)

Теперь в основной области кода, потому что мы будем говорить с VB6, мы должны быть в правильном потоке, поэтому возьмите SyncContext. И настроить темы.

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   

В нашем классе VB6, который использует этот компонент.

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

Я обнаружил, что даже если вы используете CustomEvent, он всегда связан, поэтому вы не можете просто определить, что нет связанных делегатов событий, и отключиться. Когда вы вызываете событие, если хост-приложение было закрыто, событие не устанавливает для живого значения значение true, и вы можете предположить, что оно было прервано.

...