Skip to content

Exception Handling

jbe2277 edited this page Oct 17, 2015 · 4 revisions

Unhandled exceptions thrown in a task are propagated back via the Task object. By using the await keyword the exception can be catched simply by a try/catch block. The intention with await was to simplify the asynchronous programming in a way that it feels like calling synchronous (blocking) methods. But in some cases this might be an over-simplification because it can happen that a task faults with more than one Exception. This could happen with combinators like the Task.WhenAll method. The Task itself stores all Exceptions in a Wrapper: The AggregateException. If you are programming against the Task directly then you are able to investigate all Exceptions.

Handle all Exceptions thrown by a Task

Task task = Task.Factory.StartNew(() => 
{ 
    throw new UnauthorizedAccessException(); 
}); 
try
{
    task.Wait();
}
catch (AggregateException ex)
{
    ex.Handle(x =>
    {
        if (x is UnauthorizedAccessException)
        {
            // Handle this exception...
            return true;
        }
        // Other exceptions will not be handled here.
        return false;
    });
}

However, in my experience the design decision for this exception handling simplification when using await was a good one. Until now I had never the need to handle all exceptions. It was sufficient for my scenarios to investigate just the first one because it was mostly the only one.

In some scenarios it is better to call an asynchronous method in a synchronous (blocking) way. This might be because we know that the method never takes much time and it would need a lot code to ensure that the user cannot continue to work with the user interface (e.g. avoid re-entrance or race conditions). We can do this by calling the Task.Wait method. But then we have to write the more complex exception handling code which investigates all inner exceptions of the AggregateException (see code snipped above).

If we would like to write the exception handling code in the same way as we would do with the await keyword then we have to call the following method:

task.GetAwaiter().GetResult();    // instead of task.Wait();

Further readings

Clone this wiki locally