3

このコードを使用して、WinForm アプリケーションの UnhandledException をキャッチします。

[STAThread]
static void Main(string[] args)
{
    // Add the event handler for handling UI thread exceptions to the event.
    Application.ThreadException += new
      System.Threading.ThreadExceptionEventHandler(Application_ThreadException);

    // Set the unhandled exception mode to force all Windows Forms errors 
    // to go through our handler.
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

    // Add the event handler for handling non-UI thread exceptions to the event. 
    AppDomain.CurrentDomain.UnhandledException += 
        new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    try
    {
        Application.Run(new MainForm());
    } catch....

そこで、アプリケーションを再起動しようとします。今私の問題は、このような例外をシミュレートすることです。(メインで)試す前に試しました:throw new NullReferenceException("test");VSがそれをキャッチしました。

ボタンを使用してMainFormコードでも試しました:

    private void button1_Click(object sender, EventArgs ev)
    {         
        ThreadPool.QueueUserWorkItem(new WaitCallback(TestMe), null);
    }

    protected void TestMe(object state)
    {
        string s = state.ToString();
    }

リリースモードでも、VSはそれをキャッチしました。

  • 最後に、アプリケーションを強制的に生成するにはどうすればよいUnhandleldExceptionですか?
  • でアプリケーションを再起動できますCurrentDomain_UnhandledExceptionか?
  • どうすれば生成できThreadExceptionますか?

PS。

VSの外でWindowsの汎用ウィンドウを起動すると

Application MyApplication" でエラーが発生したため、閉じる必要があります...blabla...レポートを送信する/送信しないでください。

私は、しかし、VSは、このメソッドを入力したいです (...Domain_Unhahdled...)

編集: アプリケーションを再起動するとき、次のよう に表示される Windowsクラッシュメッセージを無効にすることは可能 ですか?

コード:

static void CurrentDomain_UnhandledException(object sender, 
    UnhandledExceptionEventArgs e)
{
    // Since we can't prevent the app from terminating
    // log this to the event log.
    Logger.LogMessage(ERROR, errorMsg);
    Application.Restart();
4

2 に答える 2

6

私はまだ質問を完全に理解しているとは言えませんが、いくつか言及する必要があります。

  • Application.ThreadExceptionWindows フォーム スレッドにApplication.SetUnhandledExceptionModeのみ適用されます。任意ThreadPoolのスレッドは、実際には Windows フォーム スレッドではないため、Winforms アプリであっても、これらの 2 行のコードは効果がありません。

  • でイベントを登録すると、スレッドで発生する例外AppDomain.CurrentDomain.UnhandledException トラップされます。ThreadPool

  • ただしUnhandledExceptionイベントは実際には例外を処理できません。その時までに、プロセスの終了を止めるには遅すぎます。これは、バックグラウンド スレッドで例外が発生した場合に常に発生します (従来の .NET 1.1 の動作を有効にしていない限り、しかし... しないでください)。このイベントはロギングまたはクリーンアップにのみ適しています。

あなたと同様のテストコードを使用してこれを自分でテストし、例外「ハンドラー」内のコードが実行されることを確認しました。ただし、アプリは引き続きクラッシュし、停止することはできません。

更新:これをもう一度試してみます。

無人のアプリケーションを常に実行することが目的の場合、正確に 3 つのオプションがあります。

  1. 例外を適切に処理します。これは、断然最良であり、おそらく唯一の正しい解決策です。フックAppDomain.UnhandledExceptionは例外を処理していません。コントロールがそのイベント ハンドラーに入るまでに、アプリケーションは既にクラッシュしています。もう保存できません。

    バックグラウンド スレッドからエスケープされる未処理の例外は、修正が必要なコード内の壊滅的なバグです。バックグラウンド スレッドからエスケープされる未処理の例外は、修正が必要なコード内の壊滅的なバグです。バックグラウンド スレッドからエスケープされる未処理の例外は、修正が必要なコード内の壊滅的なバグです。 「どうでもいい」という趣旨のコメントはこれ以上やめてください。気にかけ始める必要があります。

  2. アプリケーションを再起動するようWindowsに丁寧に依頼してください。 クラッシュ ハンドラーからの再起動を試みるのとは異なり、理由が多すぎて完全に列挙できないため (データの破損、無限の再起動ループ、リソース リーク、OS の不安定性など)、信じられないほど悪い考えですが、再起動を登録すると、実際に再起動を行うことができます。半ば制御されたファッション。コメントで述べたように、.NETでこの API を相互運用するのは簡単です。アプリケーションがクラッシュして信頼できない状態になったときではなく、アプリケーションが起動したらすぐに登録します。

  3. アプリケーションを監視し、クラッシュした場合に再起動するスーパーバイザ サービスを作成します。これは、前の 2 つのポイントで説明した多くの理由からまだ悪いですが、少なくともある程度の安定性があれば、戦うチャンスがあります。

    名前付きミューテックスを使用し、スーパーバイザでそれを待機し、( .NET で)WAIT_ABANDONED状態を監視することにより、アプリケーション クラッシュのかなり信頼できる兆候を得ることができます。AbandonedMutexException放棄された状態は、ミューテックスを所有するプロセスが解放せずに終了した場合、つまり未処理の例外がある場合にのみ発生します。また、もう少し相互運用ハッキングを行うことで、クラッシュ ウィンドウを検出して閉じることもできます。

それらはあなたのオプションです。バックグラウンド スレッドからエスケープされる未処理の例外は、修正が必要なコード内の壊滅的なバグであるため、バックグラウンド スレッドで例外を処理することを強くお勧めします。 それが外部コンポーネントからのものであり、それを捕まえることができない場合、壊滅的なバグはそのコンポーネントにあり、作成者に報告するか、別のコンポーネントを使用することを検討する必要があります。

「このアプリケーションは常に実行する必要があり、致命的なクラッシュを完全に無視する必要があります」という単純な要件があるだけでは、アプリが実際に実行し続けるほど安定していない場合、そのシナリオは実現しません。クラッシュはクラッシュです。エンジンが突然停止した場合に、すぐに再始動するように車を設計することはありません。あなたができる最善の方法は、信頼できるオペレーターに依頼することです。それが人間のオペレーター、オペレーティング システム、または監視ソフトウェアのいずれであっても、代わりにアプリケーションを再起動するよう依頼することです。

この質問のバリエーションは非常に頻繁に出てくるようです。基本的には、「私のアプリは決してクラッシュしてはならない、またはクラッシュしても見えないようにする必要があります。ハンドルされていない例外をすべて食べて、それが起こらなかったふりをしたい」というものです。それは不可能であるだけでなく、事実上、優れた設計のすべての原則に反します (特に、「フェイル ファスト」の原則は、再解釈することはできますが、完全に無視してはなりません)。

それが私が言えるすべてです。それを受け入れたくない場合は、実行可能な代替手段を見つけてください。

于 2010-05-19T00:14:12.307 に答える
0

Visual Studio は例外で中断するように設定されている場合がありますが、コードのステップ実行を続けると、目的のパスをたどるはずです。また、VS の外部でアプリを実行してみてください。

未処理の例外の後でアプリケーションを再起動することは、(定義上) 不明な状態にあるため、お勧めできません。例外条件が変更されない場合、可能であれば再起動すると、再起動の無限ループに陥る可能性があります。代わりに、クラッシュを調査して修正できるように、例外情報を Web サーバーに記録することを検討してください。ただし、クラッシュ データをアップロードする前に、必ずユーザーの許可を得てください。

于 2010-05-18T22:18:02.853 に答える