2

メイン アプリケーション スレッド以外のスレッドからスローされた例外が、DispatcherUnhandledException イベント ハンドラーによってキャッチされないことに気付きました。したがって、次のように手動でスローする必要があります。

Task.Factory.StartNew(() =>
{
    throw new Exception("oops! something went wrong...");

}).ContinueWith((task) =>
{
    if (task.IsFaulted)
    {
        App.Current.Dispatcher.Invoke(new Action(() =>
        {
            throw task.Exception.InnerExceptions.First();
        }));
    }
});

ただし、作成するすべてのタスクに上記の ContinueWith メソッドを追加したくありません。これを自動的に処理する方法があればいいのにと思います。

4

1 に答える 1

2

次のクラスは、この問題を解決します。

/// <summary>
/// Extends the System.Threading.Tasks.Task by automatically throwing the first exception to the main application thread.
/// </summary>
public class TaskEx
{
    public Task Task { get; private set; }

    private TaskEx(Action action)
    {
        Task = Task.Factory.StartNew(action).ContinueWith((task) =>
        {
            ThrowTaskException(task);
        });
    }

    public static TaskEx StartNew(Action action)
    {
        if (action == null)
        {
            throw new ArgumentNullException();
        }

        return new TaskEx(action);
    }

    public TaskEx ContinueWith(Action<Task> continuationAction)
    {
        if (continuationAction == null)
        {
            throw new ArgumentNullException();
        }

        Task = Task.ContinueWith(continuationAction).ContinueWith((task) =>
        {
            ThrowTaskException(task);
        });

        return this;
    }

    private void ThrowTaskException(Task task)
    {
        if (task.IsFaulted)
        {
            App.Current.Dispatcher.Invoke(new Action(() =>
            {
                throw task.Exception.InnerExceptions.First();
            }));
        }
    }
}

これで、次のコードを簡単に使用できます (Task クラスとまったく同じです)。

TaskEx.StartNew(() =>
{
    // do something that may cause an exception
}).ContinueWith((task) =>
{
    // then do something else that may cause an exception
}).ContinueWith((task) =>
{
    // then do yet something else that may cause an exception
});

ただし、Task クラスとは異なり、これらのスレッドのいずれかからスローされた例外は、DispatcherUnhandledException イベント ハンドラーによって自動的にキャッチされます。

于 2012-09-28T00:22:10.900 に答える