当 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
这工作正常,直到我在收到此异常时将其合并到现有程序中:
检测到 CallbackOnCollectedDelegate 消息:对“AISLogger!AISLogger.Module1+ConsoleEventDelegate::Invoke”类型的垃圾收集委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。将委托传递给非托管代码时,托管应用程序必须使它们保持活动状态,直到保证它们永远不会被调用。
大量搜索表明问题是由未引用的委托对象引起的,因此超出了范围,因此被垃圾收集器处理掉了。这似乎可以通过在上面示例中的主循环中添加 GC.Collect 来确认,并在关闭控制台窗口或按 ctrl-C 时获得相同的异常。问题是,我不明白“引用代表”是什么意思?这对我来说听起来像是将变量分配给函数???我怎样才能在VB中做到这一点?有很多这样的 C# 示例,但我无法将它们翻译成 VB。
谢谢。