7

これは前の質問に関連しています。

私が今理解しようとしているのは、UIスレッドの例外がアプリケーションを終了するのを防ぐことができるのに、UI以外の例外はできないのはなぜかということです。

参考までに、この例を参照してください。

最も重要なことは、その場合に私ができることは、エラーレポートを送信するかどうかを尋ねるWindowsダイアログボックスを表示せずに、プロセスを「サイレントに」終了することです。

これは私のAppDomainUnhandledExceptionHandlerです:

private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{            
    try
    {
        // Maybe do some logging here if allowed
    }
    catch
    {
    }

    // then just terminate the application
    Application.Exit();            
}

更新この回答
のコメントに照らして、最も重要なこととして、UIスレッドがメカニズムを介して未処理の例外を早期にキャッチできるようにするメカニズムについて詳しく知りたいことを明確にしておきたいと思います。そして、そのような振る舞いを非UIスレッドに実装できるかどうか。Application.ThreadException

4

3 に答える 3

8

グーグルでさらに検索を行った後、私はこの非常に興味深い説明を見つけました。これは、ジェフ・アトウッドが彼のブログで説明したのと同じ問題に与えられたものです。

みなさん、こんにちは。混乱してすみません。この動作は実際には設計ですが、設計が少し複雑になる場合があります。

最初に理解することは、UnhandledExceptionイベントは未処理の例外「ハンドラー」ではないということです。ドキュメントに記載されている内容とは異なり、イベントに登録すると、未処理の例外が処理されることはありません(それ以降、未処理の例外は処理されませんが、循環論法で停止します...)UnhandledExceptionイベントは、スレッドまたはアプリケーションが停止する前に状態を保存しようとする場合に備えて、例外が処理されなくなったことを通知するだけです。FWIW、ドキュメントを修正するためのバグを報告しました。

複雑にするために、v1.0および1.1では、未処理の例外が必ずしもアプリケーションが停止することを意味するわけではありませんでした。未処理の例外がメインスレッドまたはアンマネージコードで存続を開始したスレッド以外で発生した場合、CLRは例外を処理し、アプリの続行を許可しました。これは一般的に悪でした。たとえば、アプリケーションが実際に作業を行わなくなるまで、ThreadPoolスレッドが1つずつサイレントに停止することがよくあるためです。この種の失敗の原因を突き止めることはほとんど不可能でした。これが、ジェフが以前は機能したと思った理由かもしれません...彼は常に非メインスレッドでクラッシュが発生するのを見ました。

v2.0では、スレッドで未処理の例外が発生すると、アプリケーションが停止します。上記のハングやサイレントストップオブワークの問題をデバッグするよりも、クラッシュをデバッグする方が非常に簡単であることがわかりました。

ところで、私の1.1マシンでは、MSDNの例に期待どおりの出力があります。デバッガーを接続する(または接続しない)まで、2行目が表示されないだけです。v2では、デバッガーが接続する前にUnhandledExceptionイベントが発生するように変更しました。これは、ほとんどの人が期待していることのようです。

JonathanKeljoCLR例外PMJonathanKeljo、2005年2月18日22:02

ただし、UIスレッドが、すべてのUIスレッド例外に対してキャッチオールハンドラーを使用できるようにするというトリックをどのように実現するかについては、まだ興味があります。

さらに、自分のアプリケーションでのみ.NET JITデバッグダイアログを無効にする方法に非常に興味がありますここに示すように、マシン全体で無効にすることはありません) 。

于 2009-08-19T17:50:46.053 に答える
3

AppDomain 例外によってアプリケーションが終了するわけではありません。未処理の例外 (あらゆる種類の) によって AppDomain が破棄され、アプリケーションが終了します。

ここでの問題は、かなり高いレベルで UI スレッドの例外を明示的に処理できることです。ただし、バックグラウンド スレッドで未処理の例外が発生した場合、同じレベルで簡単に処理する方法がないため、アプリケーションを上に伝搬して下に移動する傾向があります。Application.ThreadException を使用すると、少なくともこれがエラーの原因であることがわかり、必要に応じてログに記録できます。

UI スレッドで未処理の例外が発生すると、同じことが起こります。

于 2009-08-19T17:10:49.177 に答える
2

これはまったく役に立ちますか?

.NET2.0での未処理の例外動作の改善

また、このコードは「静かに死ぬ」ようです。あなたは何か他のものを探していますか?

using System;

namespace UnhandledException
{
    class Program
    {
        static void Main(string[] args)
        {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;

            throw new NotImplementedException();
        }

        static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            Exception exception = (Exception)e.ExceptionObject;
            System.Console.WriteLine("exception=[" + exception.ToString() + "]");

            Environment.Exit(-1);
        }   
    }
}
于 2009-08-19T17:46:10.230 に答える