One of the attendees at the p&p Symposium had some questions about how exceptions are handled in the Task Parallel Library. This is covered both in the book and in the MSDN library (references below).
But… Here’s a quick summary with code examples.
Observe by waiting
WaitAny/WaitAll will throw an AggregateException if the task being waited on threw:
Observe with a continuation task
A continuation task can examine the antecedent task’s Exception property and thereby observe it:
Observe with the unobserved exception handler
Use the scheduler’s UnobservedTaskException handler to to process exceptions and mark them as observed:
This is a last line of defense. It may be appropriate for handling completely unexpected exceptions from plugins for example. The handler runs on the finalizer thread so it’s probably too late for your application to really recover from this.
What happens when you don’t observe an exception?
The short answer is… VERY BAD THINGS. You’ll see an error like this…
A Task’s exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.
The call stack will be very unhelpful because the exception was observed and thrown on the GC’s finializer thread.
mscorlib.dll!System.Threading.Tasks.TaskExceptionHolder.Finalize() + 0x29c bytes
[Native to Managed Transition]
This makes it very hard to figure out which of your tasks caused the problem. The best way to resolve issues like this is to debug with break on unhandled exceptions and/or break when thrown set to see what’s being thrown and where before it gets cleaned up on the finalizer thread.
Parallel Tasks, Handling Exceptions (from our book)
Exception Handling (MSDN Library)