8

AggregateException.InnerExceptions.Count> 1の場合、誰かがケースに直面したことがありますか?

たとえば、TPL は、タスク本体で発生した例外をラップしますAggregateException。しかし、複数の内部例外が存在する状況を見たことがありません。

これはTPLでどのように達成できますか? FCL (または別の広く使用されているライブラリ) クラスでこれをどの
ように達成できますか (サンプルが役立ちます)?

のそのようなインスタンスを構築する可能性があることは知っていますAggregateExceptionが、問題は実践に関するものです。理解したいので、これについて質問しています。これを処理する最善の方法は何ですかAggregateException

4

2 に答える 2

8

典型的なケースは、タスクが複数のタスクに依存しており、それらのタスクの複数が例外をスローする場合です。例えば:

var t1 = Task.Factory.StartNew( () => { throw new Exception(); } );
var t2 = Task.Factory.StartNew( () => Console.WriteLine("Innocuous") );
var t3 = Task.Factory.StartNew( () => { throw new Exception(); } );

// Output: 2
var t4 = Task.WhenAll(t1, t2, t3)
             .ContinueWith(t => Console.WriteLine(t.Exception.InnerExceptions.Count), 
                           TaskContinuationOptions.OnlyOnFaulted);
于 2013-04-23T14:01:14.917 に答える
1

アニが言ったように、これらは例外を観察するために継続を使用しAggregateExceptionsて複数の連続した s を介して作成できます。Task

Task t1 = Task.Factory.StartNew(() => { throw new Exception(); });
Task t2 = Task.Factory.StartNew(() => { throw new Exception(); });
Task t3 = Task.WhenAll(t1, t2)
    .ContinueWith(t => t.Exception.InnerExceptions.Count(), 
    TaskContinuationOptions.OnlyOnFaulted);

通常AggregateException、継続内で処理します。Task継続は、継続元タスクの例外プロパティによって、継続元によって例外がスローされたかどうかを確認できます。以下は、a の結果をNullReferenceExceptionコンソールに出力します。

Task task1 = Task.Factory.StartNew (() => { throw null; });
Task task2 = task1.ContinueWith (ant => Console.Write(ant.Exception());

task1が例外をスローし、この例外が継続によってキャプチャ/クエリされない場合、処理されていないと見なされ、アプリケーションが終了します。Status継続では、キーワードを介してタスクの結果を確立するだけで十分です

asyncTask.ContinueWith(task =>
{
    // Check task status.
    switch (task.Status)
    {
        // Handle any exceptions to prevent UnobservedTaskException.             
        case TaskStatus.RanToCompletion:
            if (asyncTask.Result)
            {
                // Do stuff...
            }
            break;
        case TaskStatus.Faulted:
            if (task.Exception != null)
                mainForm.progressRightLabelText = task.Exception.Flatten().Message;
            else
                mainForm.progressRightLabelText = "Operation failed!";
        default:
            break;
    }
}

上記では、単一の例外のみを想定しています。これが確実に呼び出されるようにするためFlatten()です。他のタイプの例外が予想される場合はInnerException、必要に応じて s を反復処理できます。

これが役立つことを願っています。

于 2013-04-23T14:13:51.860 に答える