1

UI スレッドでスローされた例外が呼び出しスレッドでキャッチされない場合があります。

using System;
using System.Diagnostics;
using System.Threading;
using System.Windows;

namespace SynchronisationContextAndExceptionWPF
{
    public partial class MainWindow : Window
    {
        private readonly SynchronizationContext _synchronizationContext;

        public MainWindow()
        {
            InitializeComponent();

            _synchronizationContext = SynchronizationContext.Current;
        }


        private void Button_OnClick(object sender, RoutedEventArgs e)
        {
            try
            {
                _synchronizationContext.Send(
                    x =>
                    {
                        try
                        {
                            DoSomethingOnUiThreadThatThrowsException();
                        }
                        catch (Exception)
                        {
                            Debug.WriteLine("Catched Exception in thread that threw it.");
                            throw;
                        }
                    }, null);
            }
            catch (Exception)
            {
                Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
                throw;
            }
        }

        private static void DoSomethingOnUiThreadThatThrowsException()
        {
            throw new Exception("Any Exception...");
        }
    }
}

最初に、それは不可能だと思いました (私が見つけたすべてのドキュメントは、そこで例外をキャッチできると述べています)。いくつかの再調査の後、問題が見つかりました。私のアプリケーションは UnhandledExceptionHandler を使用しています。DispatcherUnhandledException-Eventを処理します。ユーザーとセットにいくつかの情報を表示していますe.Handled = true;

using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;

namespace SynchronisationContextAndExceptionWPF
{
    public partial class App : Application
    {
        public App()
        {
            DispatcherUnhandledException += App_DispatcherUnhandledException;
        }

        private static void App_DispatcherUnhandledException(
            object sender,
            DispatcherUnhandledExceptionEventArgs e)
        {
            Debug.WriteLine("Catched Exception in UnhandledExceptionHandler.");

            // This line makes the difference:
            e.Handled = true;
        }
    }
}

質問: DispatcherUnhandledException-Event を処理しても -Event が発生するのはなぜですか? この状況をどのように解決しますか?

4

2 に答える 2

1

多くのコントロールがある場合は、特別な例外変数を記憶する新しいクラスを生成できます。したがって、_synchronizationContext の初期化を変更するだけで済みます (できれば、コントロールの基本クラスで 1 回だけ)。

public partial class MainWindow : Window
{
    private readonly MySynchronizationContext _synchronizationContext;

    public MainWindow()
    {
        InitializeComponent();

        _synchronizationContext = new MySynchronizationContext(SynchronizationContext.Current);

    }

    private void button_Click(object sender, RoutedEventArgs e)
    {
        try
        {
            _synchronizationContext.Send(
                x =>
                {
                    DoSomethingOnUiThreadThatThrowsException();
                }, null);
        }
        catch (Exception)
        {
            Debug.WriteLine("Catched Exception in thread that calles Send-Method.");
            throw;
        }
    }

    private static void DoSomethingOnUiThreadThatThrowsException()
    {
        throw new Exception("Any Exception...");
    }
}

class MySynchronizationContext
{
    SynchronizationContext innerContext;

    public MySynchronizationContext(SynchronizationContext ctx)
    {
        innerContext = ctx;
    }

    public virtual void Send(SendOrPostCallback d, object state)
    {
        Exception threadException = null;

        try
        {
            innerContext.Send(_ =>
            {
                try
                {
                    d.Invoke(state);
                }
                catch (Exception exception)
                {
                    threadException = exception;
                }
            }, null);
        }
        catch (Exception ex)
        {

        }

        if (threadException != null)
        {
            throw new Exception("Synchronization error", threadException);
        }
    }
}
于 2016-01-12T14:30:12.477 に答える