0

私はこの単純なTPLコードを持っています:

var t = Task.Factory.StartNew(() => { throw null; })
    .ContinueWith((ant) => { Console.WriteLine("Success"); }, 
        TaskContinuationOptions.OnlyOnRanToCompletion)
    .ContinueWith((ant) => { Console.WriteLine("Error"); }, 
        TaskContinuationOptions.OnlyOnFaulted);
t.Wait();

未処理の例外が発生します:

Unhandled Exception: System.AggregateException: One or more errors occurred.
...

t.Wait()を入力すると、例外がtry-catchそこでキャッチされ、例外継続を使用するという全体的なポイントに反することがわかります。ここで、完了継続を削除すると、タスクによってスローされた例外は例外継続で処理され、上記の例外は発生しません。誰かが起こっていることに光を当てることができますか?.NET4.0でVS2010SP1を使用しています

4

1 に答える 1

3

ContinueWith()元の値を返しません。継続を表すをTask返します。Taskそして、あなたの場合、オリジナルTaskが完全に実行されなかったので、その継続はキャンセルされます。そして、2番目Taskが失敗しなかったので、3番目Taskもキャンセルされました。それがあなたがTaskCanceledException中に包まれている理由ですAggregateException

代わりにできることは、両方のアクションを実行する1つの継続を行うことです。何かのようなもの:

var t = Task.Factory.StartNew(() => { throw null; })
    .ContinueWith(
        ant =>
        {
            if (ant.IsFaulted)
                Console.WriteLine("Error");
            else
                Console.WriteLine("Success");
        });

このようなことを頻繁に行う場合は、このための拡張メソッドを作成できます(さらにTask<T>Action<T>asの汎用バージョンも作成できますonSuccess)。

public static Task ContinueWith(
    this Task task, Action onSuccess, Action<AggregateException> onError)
{
    return task.ContinueWith(
        ant =>
        {
            if (ant.IsFaulted)
                onError(task.Exception);
            else
                onSuccess();
        });
}

使用法:

var t = Task.Factory.StartNew(() => { throw null; })
    .ContinueWith(
        () => { Console.WriteLine("Success"); },
        ex => { Console.WriteLine("Error"); });
t.Wait();

Taskまた、これは、オリジナルがキャンセルされないことを知っていることを前提としています。そうでない場合は、もう1つのケースを処理する必要があります。

于 2012-10-24T17:48:21.897 に答える