Exception handling in the .NET Task Parallel Library with C#: using Handle()
February 12, 2014 Leave a comment
In this post we saw how to catch unhandled exceptions thrown by tasks. Recall that the AggregateException object has a list of inner exceptions thrown by the tasks that are waited on.
You may want to handle each type of exception in a different way. There may be types of exception that you can handle locally and some other unexpected ones that should be propagated further up the stack trace. The AggregateException object has a Handle() method where you can specify the action taken depending on the type of the inner exception. The function should return true if the exception can be dealt with locally and false if it should be propagated upwards.
Construct two tasks using the cancellation token in the first one:
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); CancellationToken cancellationToken = cancellationTokenSource.Token; Task firstTask = Task.Factory.StartNew(() => { cancellationToken.WaitHandle.WaitOne(-1); throw new OperationCanceledException(cancellationToken); }, cancellationToken); Task secondTask = Task.Factory.StartNew(() => { throw new NullReferenceException(); });
The effect of WaitHandle.WaitOne(-1) is to wait forever until the token has been cancelled.
Cancel the token which will interrupt the first task:
cancellationTokenSource.Cancel();
Wait for the tasks, catch the AggregateException and call its Handle method:
try { Task.WaitAll(firstTask, secondTask); } catch (AggregateException ex) { ex.Handle((innerException) => { if (innerException is OperationCanceledException) { return true; } else { return false; } } }
We declare that OperationCanceledException is an expected type and can be dealt with locally. All other types should be re-thrown.
If you run the above code in a console app make sure to run it without debugging (Ctrl + F5), otherwise the code execution will unnecessarily stop when the OperationCanceledException is thrown in the first task.
You’ll see that the NullReferenceException is re-thrown as we return false for all types except for the OperationCanceledException type. Test returning true instead: the exception will be “swallowed” within the Handle method.
View the list of posts on the Task Parallel Library here.