.NET アプリですべての例外/クラッシュをキャッチする方法 [重複]
-
01-07-2019 - |
質問
.NET コンソール アプリがクラッシュし、ユーザーにメッセージが表示されます。私のコードはすべて try{<code>} catch(Exception e){<stuff>}
ブロックされますが、それでもエラーが表示されることがあります。
Win32 アプリでは、さまざまな例外ハンドラーをインストールすることで、考えられるすべての例外/クラッシュをキャプチャできます。
/* C++ exc handlers */
_set_se_translator
SetUnhandledExceptionFilter
_set_purecall_handler
set_terminate
set_unexpected
_set_invalid_parameter_handler
考えられるすべてのエラー ケースを処理/記録/停止できるようにするために、.NET の世界でこれに相当するものは何ですか?
解決
他の人が投稿したことに反して、すべての例外をキャッチすることに問題はありません。重要なのは、それらすべてを適切に処理することです。スタック オーバーフローまたはメモリ不足状態が発生した場合は、アプリをシャットダウンする必要があります。また、OOM 状態により、例外ハンドラーが正しく実行されなくなる可能性があることにも注意してください。たとえば、例外ハンドラーが例外メッセージを含むダイアログを表示する場合、メモリが不足していると、ダイアログを表示するための十分なメモリが残っていない可能性があります。記録してすぐにシャットダウンするのが最善です。
他の人が述べたように、見逃される可能性のあるコレクション例外を処理できる UnhandledException および ThreadException イベントがあります。次に、メイン ループの周りに例外ハンドラーをスローするだけです (winforms アプリを想定)。
また、メモリ不足の場合に OutOfMemoryExceptions が常にスローされるわけではないことにも注意してください。OOM 条件は、コード内またはフレームワーク内で、実際の基礎となる条件がメモリ不足であるという事実とは必ずしも関係のない、あらゆる種類の例外をトリガーする可能性があります。根本的な原因が実際にはメモリ不足である場合に、InvalidOperationException または ArgumentException が頻繁に発生するのを目にしました。
他のヒント
AppDomain.UnhandledException イベントにイベント ハンドラーを追加すると、例外がスローされてキャッチされなかったときに呼び出されます。
ホストの Jeff Atwood によるコードプロジェクトのこの記事 必要なものです。未処理の例外をキャッチするコードと、クラッシュに関する情報をユーザーに表示するためのベスト プラクティスが含まれています。
の グローバル.asax クラスは最後の防衛線です。見る:
protected void Application_Error(Object sender, EventArgs e)
方法
一部の例外はキャッチするのが危険であるか、ほとんどキャッチできないことに注意してください。
- メモリ不足例外:catch ハンドラーで何かを行うと、(CLR のマネージド側またはアンマネージド側で) メモリが割り当てられ、別の OOM がトリガーされる可能性があります。
- スタックオーバーフロー例外:CLR が十分に早く検出したかどうかに応じて、通知が届く可能性があります。最悪の場合、プロセスが強制終了されます。
AppDomain.CurrentDomain.UnhandledException を使用してイベントを取得できます。
キャッチしているものの 全て 適切に処理する計画のない例外は確かに悪い習慣であり、アプリケーションは何らかの適切な方法で失敗するべきだと思います。クラッシュはユーザーを死ぬほど怖がらせてはなりません。少なくとも、エラーの説明、技術サポート担当者に報告する情報、そして理想的にはアプリケーションを閉じて再起動するためのボタンが表示されるべきです。理想的な世界では、アプリケーションはユーザー データをディスクにダンプし、それを回復しようとすることができるはずです (しかし、これは要求が多すぎることがわかります)。
とにかく、私は通常次のものを使用します:
AppDomain.CurrentDomain.UnhandledException
Application.ThreadException Event を使用することもできます。
かつて私は、COM ベースのアプリケーション内で実行される .NET アプリを開発していました。この場合、AppDomain.CurrentDomain.UnhandledException が機能しなかったため、このイベントは非常に役に立ちました。
すべての例外をキャッチするのではなく、それらをユーザーに表示する方がよいと思います。その理由は、実際に処理できる例外のみをキャッチする必要があるためです。プログラムを停止させる何らかの例外が発生したにもかかわらずそれをキャッチした場合、さらに深刻な問題が発生する可能性があります。こちらもお読みください よくある質問:FxCop が catch(Exception) に対して警告するのはなぜですか?.
これらのハンドルされない例外をキャッチすると、アプリケーションのセキュリティ要件が変更される可能性があることに注意してください。アプリケーションは、特定のコンテキスト (ネットワーク共有から実行する場合など) で正しく実行されなくなる可能性があります。必ず徹底的にテストしてください。
両方のappdomain.currentdomain.unhandledexception application.threadexceptionを使用することは害はありません
ただし、セカンダリ スレッドの例外はこれらのハンドラーではキャッチされないことに注意してください。使用 セーフスレッド 必要に応じてセカンダリスレッド用