0

バックグラウンド ワーカーを使用していますが、RunWorkerCompleted イベント ハンドラーで発生した新しい例外が Application.ThreadException ハンドラーに表示されないことがわかりました。例: Program.cs のどこか:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.ThreadException += delegate(object o, ThreadExceptionEventArgs args)
        {
            if (args.Exception != null)
                Console.WriteLine("thread error {0}", args.Exception.Message);
        };

        Application.Run(new Form1());
    }

次に、ボタンをクリックします(テスト目的のみ)

        var bw = new BackgroundWorker();
        bw.DoWork += delegate(object o, DoWorkEventArgs args) { /* some calculations here */ };
        bw.RunWorkerCompleted += delegate(object sender1, RunWorkerCompletedEventArgs eventArgs)
        { 
            try
            {
                //in run worker completed exception occurs
                throw new ApplicationException("test exception 1");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("throwing new exception");
                throw new ApplicationException(string.Format("catched '{0}'", ex.Message), ex);
            }
        };

        bw.RunWorkerAsync();

プログラムの出力は次のとおりです。

テスト例外 1

新しい例外を投げる

スレッド エラー テスト例外 1

私は Application.ThreadException ハンドラー例外で、元の例外ではなく、テキストスレッドエラーがキャッチされた「テスト例外1」が表示されるはずだと信じています。

私を助けていただけますか - なぜそれが起こるのか、どうすれば解決できるのでしょうか? これはサンプルコードです。実際のコードでは、RunWorkerCompleted ハンドラー内にネストされたメソッドがいくつかあります。そして、それらのメソッドのいくつかは、例外をキャッチし、内部例外に追加情報と元の例外を追加して新しいものをスローします。したがって、 Application.ThreadException ハンドラーでは、スローされた元の例外だけでなく、チェーン全体も取得したいと考えています。

ありがとうございました


ボタンクリックによる未処理の例外に対して GetBaseException が呼び出されないことがわかりました(たとえば)

以下のように、Program.Main メソッドに TreadException イベント ハンドラがあるとします。

        Application.ThreadException += (o, args) =>
        {
            Console.WriteLine("BEGIN ThreadException handler");
            ShowException(args.Exception);
            Console.WriteLine("END ThreadException handler\r\n");
        };

および Program.ShowException メソッドは次のようになります。

    static void ShowException(Exception ex)
    {
        var tab = "";
        while (ex != null)
        {
            Console.WriteLine("{1}error '{0}'", ex.Message, tab);
            tab += '\t';
            ex = ex.InnerException;
        }
    }

コードの場合

        try
        {
            throw new ApplicationException("button click 1");
        }
        catch (Exception ex)
        {
            throw new ApplicationException(string.Format("BC caught '{0}'", ex.Message), ex);
        }

ボタンクリックで実行されると、次の出力が生成されます。

BEGIN ThreadException ハンドラー

エラー 'BC が 'ボタン クリック 1'' をキャッチしました

  • エラー「ボタンクリック 1」*

END ThreadException ハンドラー

ご覧のとおり、例外チェーン全体が利用可能です。

ただし、ThreadException ハンドラーは、RunWorkerCompleted イベント ハンドラーで非常によく似たコードの元の例外のみを表示します (以下のコードはボタン クリック イベントで実行されました)。

        var bw = new BackgroundWorker();
        bw.DoWork += delegate(object o, DoWorkEventArgs args) 
        { 
            /* some calculations here */
        };
        bw.RunWorkerCompleted += delegate(object sender1, RunWorkerCompletedEventArgs eventArgs)
        { 
            try
            {
                //in run worker completed exception occurs
                Console.WriteLine("RWC exception test, throwing");
                throw new ApplicationException("test exception 1");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine("RWC got exception, throwing new");
                throw new ApplicationException(string.Format("RWC caught '{0}'", ex.Message), ex);
            }
        };

        bw.RunWorkerAsync();

出力は以下のとおりです。

RWC 例外テスト、スロー

テスト例外 1

RWC で例外が発生し、新しいものがスローされました

BEGIN ThreadException ハンドラー

error 'test exception 1' -- 元の例外のみ

END ThreadException ハンドラー

GetBaseException は RunWorkerCompleted イベントに対してのみ実行されるようです。

4

1 に答える 1

1

何らかの理由で、フレームワークはスローした例外を呼び出し、そのException.GetBaseException例外を使用してイベントに渡します。それが望ましくない場合は、基本/内部例外を渡さないでください。ThreadException

于 2012-09-18T16:40:03.727 に答える