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 に翻訳することはできません。
ありがとう。