This blocking mechanism can be rephrased as:
Task.WhenAll(taskA, taskB, taskC).Wait()
This gives you a task back which we can await but can also manage cancellation from. So, to ignore cancellation exception, you can do the following:
Task.WhenAll(taskA, taskB, taskC).ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled).Wait();
Which won't throw an OperationCancelledException
.
This could then be wrapped into an extension method as follows:
public static class TaskExtensions
{
public static Task IgnoreCancellation(this Task task)
{
return task.ContinueWith(t => { }, TaskContinuationOptions.OnlyOnCanceled);
}
}
Which would allow you to write the following, again without encountering an OperationCancelledException
:
Task.WhenAll(taskA, taskB, taskC).IgnoreCancellation().Wait();
Here's a test fixture showing the approach working:
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();
}
}
Hope it helps.
CancellationToken
toWaitAll
if you don't want to get an exception? – MessroomAggregateException
if at least one task is cancelled. Want or not, this is how they designed it, you have no other choice than usingtry/catch
. – Messroom