這種阻塞機制可以表述爲:
Task.WhenAll(taskA, taskB, taskC).Wait()
這給你一個任務回來,我們可以等待,但也可以從管理取消。所以,忽略消除異常,可以進行以下操作:
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);
}
}
這將讓你沒有遇到一個OperationCancelledException
寫以下,再次:
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();
}
}
希望它hel PS。
這是[記錄](https://msdn.microsoft.com/en-us/library/dd321280(v = vs.110).aspx)。如果你不想得到異常,爲什麼你將'CancellationToken'傳遞給'WaitAll'? –
我通過它來取消等待,但不幸的是,即使我沒有通過它,它也會拋出這個異常。 @IvanStoev – Jacob
它也記錄瞭如果至少有一個任務被取消,你會得到'AggregateException'。不管你想不想,這就是他們設計的方式,除了使用'try/catch'之外別無選擇。 –