-
Notifications
You must be signed in to change notification settings - Fork 130
Exception Handling
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.
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();