これはほんの数日前に発見したもので、この質問から私のマシンに限定されないことが確認されました。
これを再現する最も簡単な方法は、Windowsフォームアプリケーションを起動し、ボタンを追加して、次のコードを記述することです。
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
Exit()ステートメントの実行後、プログラムは失敗します。Windowsフォームでは、「ウィンドウハンドルの作成エラー」が発生します。
アンマネージデバッグを有効にすると、何が起こっているのかがいくぶん明確になります。COMモーダルループを実行し、WM_PAINTメッセージが配信されることを可能にします。それは処分されたフォームでは致命的です。
これまでに収集した唯一の事実は次のとおりです。
- デバッガでの実行に限定されません。これも1つもなければ失敗します。どちらかと言えば、WERクラッシュダイアログが2回表示されます。
- プロセスのビットネスとは何の関係もありません。wow64レイヤーはかなり悪名高いですが、AnyCPUビルドは同じ方法でクラッシュします。
- .NETバージョンとは何の関係もありません。4.5と3.5は同じようにクラッシュします。
- 終了コードは関係ありません。
- Exit()を呼び出す前にThread.Sleep()を呼び出しても修正されません。
- これは64ビットバージョンのWindows 8で発生し、Windows 7は同じ影響を受けないようです。
- これは比較的新しい振る舞いであるはずですが、私はこれを見たことはありません。私のマシンでは更新履歴が正確ではなくなっていますが、Windows Updateを通じて関連する更新が配信されていません。
- これはひどく破壊的な動作です。このようなコードをAppDomain.UnhandledExceptionのイベントハンドラーに記述すると、同じようにクラッシュします。
このクラッシュを回避するためにできることには特に興味があります。特に、AppDomain.UnhandledExceptionシナリオは私を困らせます。.NETプログラムを終了する方法は多くありません。Application.Exit()またはForm.Close()の呼び出しはUnhandledExceptionのイベントハンドラーでは無効であるため、回避策ではないことに注意してください。
更新:Mehrdadは、ファイナライザスレッドが問題の一部である可能性があることを指摘しました。私はこれを見ていると思いますし、CLRがファイナライザスレッドに実行を終了させるための2秒のタイムアウトの証拠もいくつか見ています。
ファイナライザはNativeWindow.ForceExitMessageLoop()内にあります。32ビットモードでマシンコードを見ると、コードの場所にほぼ対応するIsWindow()Win32関数があります。オフセットは0x3cです。IsWindow()がデッドロックしているようです。内部の適切なスタックトレースを取得できませんが、デバッガーはP / Invoke呼び出しが返されたと判断します。これは説明するのが難しいです。より良いスタックトレースを取得できる場合は、ぜひご覧ください。私の:
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.ForceExitMessageLoop() + 0x3c bytes
System.Windows.Forms.dll!System.Windows.Forms.NativeWindow.Finalize() + 0x16 bytes
[Native to Managed Transition]
kernel32.dll!@BaseThreadInitThunk@12() + 0xe bytes
ntdll.dll!___RtlUserThreadStart@8() + 0x27 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x1b bytes
ForceExitMessageLoop呼び出しを超えるものはなく、アンマネージデバッガーが有効になっています。
This happens on the 64-bit version of Windows 8
・ハンスはそう言った!
Exit(0)
少し前に64ビットWin7でこの種の動作に遭遇しましたが、変更ExitCode
はProcess.GetCurrentProcess().Kill()
問題なく使用するのに役立ちませんでした