これはほんの数日前に発見したもので、 この質問 から自分のマシンだけに限定されないという確認を得ました。
再現する最も簡単な方法は、Windowsフォームアプリケーションを起動し、ボタンを追加して次のコードを記述することです。
private void button1_Click(object sender, EventArgs e) {
MessageBox.Show("yada");
Environment.Exit(1); // Kaboom!
}
プログラムは、Exit()ステートメントの実行後afterに失敗します。 Windowsフォームでは、「ウィンドウハンドルの作成エラー」が発生します。
アンマネージデバッグを有効にすると、何が起こっているかがある程度明確になります。 [〜#〜] com [〜#〜] モーダルループが実行されており、WM_Paintメッセージを配信できます。廃棄されたフォームでは致命的です。
これまでに収集した唯一の事実は次のとおりです。
このクラッシュを回避するためにあなたができることには特に興味があります。特にAppDomain.UnhandledExceptionシナリオは私を困らせます。 .NETプログラムを終了する方法はあまりありません。 Application.Exit()またはForm.Close()を呼び出すことは、UnhandledExceptionのイベントハンドラーでは無効であるため、回避策ではないことに注意してください。
更新:Mehrdadは、ファイナライザスレッドが問題の一部である可能性があることを指摘しました。私はこれを見ていると思うし、CLRがファイナライザスレッドに実行を終了させる2秒のタイムアウトの証拠も見ていると思います。
ファイナライザーはNativeWindow.ForceExitMessageLoop()内にあります。コードの場所にほぼ対応するIsWindow()Win32関数があり、32ビットモードでマシンコードを見るとオフセット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呼び出しの上には何もありません。アンマネージデバッガーは有効です。
この問題についてマイクロソフトに問い合わせたところ、報われたようです。少なくとも私はそれがやったと思いたい:)。私は彼らから解決策の確認を得られなかったが、Windowsグループに直接連絡することは難しく、仲介者を使わなければならなかった。
Windows Updateを介して配信された更新プログラムが問題を解決しました。クラッシュの2秒前の顕著な遅延はなくなり、IsWindow()デッドロックが解決されたことを強く示唆しています。そして、プログラムはクリーンかつ確実にシャットダウンします。この更新プログラムは、Windows Defender、wdboot.sys、wdfilter.sys、tcpip.sys、rpcrt4.dll、uxtheme.dll、crypt32.dll、wintrust.dllのパッチをインストールしました。
Uxtheme.dllは奇妙です。 Visual StylesテーマAPIを実装し、このテストプログラムで使用されます。確かではありませんが、私のお金は問題の原因としてその上にあります。 C:\ WINDOWS\system32のコピーのバージョン番号は6.2.9200.16660で、2013年8月14日に私のマシンで作成されました。
ケースは閉じられました。
なぜ機能しないのかわかりません"any more"ですが、Environment.Exit
保留中のファイナライザーを実行します。 Environment.FailFast
しません。
(何らかの奇妙な理由のために)後で実行する必要がある奇妙な保留中のファイナライザがあり、これが発生する可能性があります。
これはなぜ発生するのかを説明しませんが、サンプルのようなボタンイベントハンドラーでEnvironment.Exit
を呼び出さず、代わりに rene's answer で提案されているメインフォームを閉じます。
AppDomain.UnhandledException
ハンドラについては、Environment.ExitCode
を呼び出すのではなく、単にEnvironment.Exit
を設定できます。
ここで何を達成しようとしているのかわかりません。 Windows Formsアプリケーションから終了コードを返す必要があるのはなぜですか?通常、終了コードはコンソールアプリケーションで使用されます。
このクラッシュを回避するためにあなたができることには特に興味があります。WERダイアログが表示されないようにするには、Environment.Exit()の呼び出しが必要です。
Mainメソッドにtry/catchがありますか? Windows Formsアプリケーションの場合、未処理の例外ハンドラーだけでなく、メッセージループを常にtry/catchします。
私たちのアプリでも同じ問題が見つかりました。次の構成で解決しました。
Environment.ExitCode=1;
Application.Exit();