Я пытаюсь закрыть консольное приложение vb.net изящно, когда происходит выключение Windows. Я нашел примеры, которые вызывают функцию SetConsoleCtrlHandler Win32, которые в основном выглядят следующим образом:
Module Module1
Public Enum ConsoleEvent
CTRL_C_EVENT = 0
CTRL_BREAK_EVENT = 1
CTRL_CLOSE_EVENT = 2
CTRL_LOGOFF_EVENT = 5
CTRL_SHUTDOWN_EVENT = 6
End Enum
Private Declare Function SetConsoleCtrlHandler Lib "kernel32" (ByVal handlerRoutine As ConsoleEventDelegate, ByVal add As Boolean) As Boolean
Public Delegate Function ConsoleEventDelegate(ByVal MyEvent As ConsoleEvent) As Boolean
Sub Main()
If Not SetConsoleCtrlHandler(AddressOf Application_ConsoleEvent, True) Then
Console.Write("Unable to install console event handler.")
End If
'Main loop
Do While True
Threading.Thread.Sleep(500)
Console.WriteLine("Main loop executing")
Loop
End Sub
Public Function Application_ConsoleEvent(ByVal [event] As ConsoleEvent) As Boolean
Dim cancel As Boolean = False
Select Case [event]
Case ConsoleEvent.CTRL_C_EVENT
MsgBox("CTRL+C received!")
Case ConsoleEvent.CTRL_BREAK_EVENT
MsgBox("CTRL+BREAK received!")
Case ConsoleEvent.CTRL_CLOSE_EVENT
MsgBox("Program being closed!")
Case ConsoleEvent.CTRL_LOGOFF_EVENT
MsgBox("User is logging off!")
Case ConsoleEvent.CTRL_SHUTDOWN_EVENT
MsgBox("Windows is shutting down.")
' My cleanup code here
End Select
Return cancel ' handling the event.
End Function
Это работает нормально, пока я не включу его в существующую программу muy, когда я получу это исключение:
Обнаружен CallbackOnCollectedDelegate Сообщение: Обратный вызов был сделан на собранном делегатом мусора типа "AISLogger! AISLogger.Module1 + ConsoleEventDelegate:: Invoke". Это может привести к сбоям приложений, сбоям и потерям данных. При передаче делегатов неуправляемому коду они должны оставаться в живых управляемым приложением, пока не будет гарантировано, что они никогда не будут вызваны.
Значительный поиск указывает на то, что проблема вызвана тем, что объект-делегат не ссылается, и поэтому выходит из сферы действия и поэтому удаляется сборщиком мусора. Это, похоже, подтверждается добавлением GC.Collect в основной цикл в приведенном выше примере и получение того же исключения при закрытии окна консоли или нажатии ctrl-C. Беда в том, что я не понимаю, что подразумевается под "ссылкой на делегата"? Это звучит для меня как назначение переменной функции? Как я могу это сделать в VB? Есть много примеров С#, но я не могу перевести их в VB.
Спасибо.