87

ではSystem.Threading.Tasks.Task<TResult>、スローされる可能性のある例外を管理する必要があります。私はそれを行うための最良の方法を探しています。これまでのところ、呼び出し内でキャッチされていないすべての例外を管理する基本クラスを作成しました。.ContinueWith(...)

それを行うためのより良い方法があるかどうか疑問に思っています。または、それが良い方法であっても。

public class BaseClass
{
    protected void ExecuteIfTaskIsNotFaulted<T>(Task<T> e, Action action)
    {
        if (!e.IsFaulted) { action(); }
        else
        {
            Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
            {
                /* I display a window explaining the error in the GUI 
                 * and I log the error.
                 */
                this.Handle.Error(e.Exception);
            }));            
        }
    }
}   

public class ChildClass : BaseClass
{
    public void DoItInAThread()
    {
        var context = TaskScheduler.FromCurrentSynchronizationContext();
        Task.Factory.StartNew<StateObject>(() => this.Action())
                    .ContinueWith(e => this.ContinuedAction(e), context);
    }

    private void ContinuedAction(Task<StateObject> e)
    {
        this.ExecuteIfTaskIsNotFaulted(e, () =>
        {
            /* The action to execute 
             * I do stuff with e.Result
             */

        });        
    }
}
4

2 に答える 2

115

使用している言語のバージョンに応じて、これを行うには 2 つの方法があります。

C# 5.0 以降

asyncおよびキーワードを使用してawait、これを大幅に簡略化できます。

asyncTask Parallel Libraryの使用を簡素化するためにawait言語に導入され、使用する必要がなくなり、トップダウンでプログラミングを続けることができます。ContinueWith

このため、次のように単純にtry/catchブロックを使用して例外をキャッチできます。

try
{
    // Start the task.
    var task = Task.Factory.StartNew<StateObject>(() => { /* action */ });

    // Await the task.
    await task;
}
catch (Exception e)
{
    // Perform cleanup here.
}

上記をカプセル化するメソッドには、使用できるようにキーワードを適用する必要があることに注意してください。asyncawait

C# 4.0 以下

次のように、 enumerationから値を取得するContinueWithオーバーロードを使用して例外を処理できます。TaskContinuationOptions

// Get the task.
var task = Task.Factory.StartNew<StateObject>(() => { /* action */ });

// For error handling.
task.ContinueWith(t => { /* error handling */ }, context,
    TaskContinuationOptions.OnlyOnFaulted);

列挙のOnlyOnFaultedメンバーは、継続元タスクが例外をスローした場合にのみ継続を実行する必要があることを示します。TaskContinuationOptions

もちろん、ContinueWith例外ではないケースを処理して、同じ前提条件をオフにするために複数の呼び出しを行うことができます。

// Get the task.
var task = new Task<StateObject>(() => { /* action */ });

// For error handling.
task.ContinueWith(t => { /* error handling */ }, context, 
    TaskContinuationOptions.OnlyOnFaulted);

// If it succeeded.
task.ContinueWith(t => { /* on success */ }, context,
    TaskContinuationOptions.OnlyOnRanToCompletion);

// Run task.
task.Start();
于 2012-10-19T19:25:07.900 に答える