当 Windows 关机时,我想要优雅地关闭我的 VB.NET 控制台应用程序。我已经找到了一些调用 Win32 函数 SetConsoleCtrlHandler 的示例,基本上都像这样:
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
这段代码运行良好,但在将其合并到现有程序时,会出现以下异常:
经过多次搜索,发现问题是由于委托对象没有被引用而导致过期被垃圾收集器处理。这似乎得到了证实,因为在上面的示例中,在主循环中添加GC.Collect并在关闭控制台窗口或按下ctrl-C时获取相同的异常。问题是,我不理解“引用委托”的含义?这对我来说听起来像是将变量分配给函数?如何在VB中执行此操作?有许多C#示例,但我无法将其翻译成VB。检测到已收集的委托回调 消息:在类型为‘AISLogger!AISLogger.Module1+ ConsoleEventDelegate :: Invoke’的垃圾已收集委托上进行了回调。 这可能导致应用程序崩溃,损坏和数据丢失。 在将委托传递给非托管代码时,必须由托管应用程序保持活动状态,直到确保永远不会调用它们。
谢谢。