このブロック機構は、と言い換えることができます。
OperationCancelledException
をスローしません
Task.WhenAll(taskA, taskB, taskC).ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled).Wait();
:だから、キャンセル例外を無視して、次の操作を行うことができます。
次のようにこれは、その後、拡張メソッドにラップすることができます
あなたが
OperationCancelledException
に遭遇することなく、再び、次のように書くことができるようになる
public static class TaskExtensions
{
public static Task IgnoreCancellation(this Task task)
{
return task.ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled);
}
}
を:
Task.WhenAll(taskA, taskB, taskC).IgnoreCancellation().Wait();
は、ここで示すテスト・フィクスチャですアプローチの仕組み:
public class IgnoreTaskCancellation
{
[Fact]
public void ShouldThrowAnAggregateException()
{
CancellationTokenSource cts = new CancellationTokenSource(10);
Task taskA = Task.Delay(20, cts.Token);
Task taskB = Task.Delay(20, cts.Token);
Task taskC = Task.Delay(20, cts.Token);
Assert.Throws<AggregateException>(() => Task.WhenAll(taskA, taskB, taskC).Wait());
}
[Fact]
public void ShouldNotThrowAnException()
{
CancellationTokenSource cts = new CancellationTokenSource(10);
Task taskA = Task.Delay(20, cts.Token);
Task taskB = Task.Delay(20, cts.Token);
Task taskC = Task.Delay(20, cts.Token);
Task.WhenAll(taskA, taskB, taskC).ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled).Wait();
}
[Fact]
public void ShouldNotThrowAnExceptionUsingIgnore()
{
CancellationTokenSource cts = new CancellationTokenSource(10);
Task taskA = Task.Delay(20, cts.Token);
Task taskB = Task.Delay(20, cts.Token);
Task taskC = Task.Delay(20, cts.Token);
Task.WhenAll(taskA, taskB, taskC).IgnoreCancellation().Wait();
}
}
ps。
[ドキュメント](https://msdn.microsoft.com/en-us/library/dd321280(v=vs.110).aspx)です。あなたが例外を受けたくない場合、なぜ 'CancellationToken'を' WaitAll'に渡すのですか? –
私はそれを渡して待機をキャンセルしますが、残念ながら、私はそれを渡さない場合でもこの例外をスローします。 @IvanStoev – Jacob
少なくとも1つのタスクがキャンセルされた場合は、 'AggregateException'を取得することも記載されています。したいかどうか、これは彼らがそれを設計する方法であり、 'try/catch'を使う以外の選択肢はありません。 –