2017-02-21 2 views
1

キャンセルトークンを受け付ける複数のタスクがあり、それに応じてThrowIfCancellationRequestedを呼び出します。これらのタスクは、Task.WhenAllを使用して同時に実行されます。タスクが例外をスローすると、すべてのタスクがキャンセルされるようにします。正しくTask.WhenAllをキャンセルし、最初の例外をスローするには?

var cts = new CancellationTokenSource(); 

try 
{ 
    var tasks = new Task[] { DoSomethingAsync(cts.Token), ... } // multiple tasks here 
     .Select(task => task.ContinueWith(task => 
     { 
      if (task.IsFaulted) 
      { 
       cts.Cancel(); 
      } 
     })); 

    await Task.WhenAll(tasks).ConfigureAwait(false); 
} 
catch (SpecificException) 
{ 
    // Why is this block never reached? 
} 

私は、これは、これを行うための最善の方法であるかどうかわからないんだけど、いくつかの問題を持っているようだ:私はこれはSelectContinueWithを使用して達成しました。例外は内部的にキャッチされ、WhenAllのコードに常に到達したようです。私は、例外が発生したときにWhenAllの後のコードに到達したくないのですが、コールスタックの別のレベルで手動でキャッチできるように例外がスローされてしまいます。これを達成する最良の方法は何ですか?可能であれば、コールスタックをそのまま残したいと思います。複数の例外が発生した場合は、最初の例外のみが再スローされた場合は、AggregateExceptionでない方が最適です。関連ノートで


、私はそうのようContinueWithにキャンセルトークンを渡してみました:task.ContinueWith(lambda, cts.Token)。しかし、任意のタスクの例外が発生した場合、これは私が興味を持っている例外の代わりにTaskCanceledExceptionを投げます。私が望むもの

+0

これはTask.WhenAll '程度であるということです'タスクの外側でtry-catchを使用します。もう一つの質問は、複数の 'ContinueWith'に参加し、task.Exceptionを明示的にチェックすることです。 –

+1

違いは関係ありません。 'WhenAll'は' ContinueWIth'を使用して独自の継続を追加するだけで、それが自分自身に障害があるかどうかを判断する際に 'Exception'値をチェックしています。 'WhenAll'の場面の後ろで起こっていることのいくつかは、問題を説明したり修正したりすることと意味が異なるわけではありません。 – Servy

+0

@Servy私はあなたの説明や他のスレッドが、通常どおりに例外をスローさせて、コールスタックの別のレベルでTPL以外の例外を処理できるようにする方法について私の質問にどう答えているのか分かりません。 –

答えて

5

ContinueWithを使用しないでください。正しい答えは、各タスクに継続を取り付けるのではなく、別の「高レベル」async方法を導入することである:この質問と「複製」の違い@Servy

private async Task DoSomethingWithCancel(CancellationTokenSource cts) 
{ 
    try 
    { 
    await DoSomethingAsync(cts.Token).ConfigureAwait(false); 
    } 
    catch 
    { 
    cts.Cancel(); 
    throw; 
    } 
} 


var cts = new CancellationTokenSource(); 
try 
{ 
    var tasks = new Task[] { DoSomethingWithCancel(cts), ... }; 
    await Task.WhenAll(tasks).ConfigureAwait(false); 
} 
catch (SpecificException) 
{ 
    ... 
} 
+2

これは素晴らしい解決策のようです。なぜこれがdownvoteを持っているか、任意のアイデア? –