Even with async/await we still have a need for using Task continuations and ofcourse we need to handle exceptions within, or from, these tasks and their continuations.
A problem can occur in a WPF application for example, where the exception seems to get lost, for example from a ICommand handler I has such a situation where I couldn’t seem to catch the exception and neither did it propagate through to any unhandled exception handlers.
In the example below, we’ll assume that RunAsync returns a Task and we want to do something after the task completes on the calling thread (for example if the calling thread was the UI thread), we might have something like this
RunAsync(). ContinueWith(tsk => { // do something UI specific }, TaskScheduler.FromCurrentSynchronizationContext());
If we have exceptions occur in the RunAsync method, then we would maybe write something like this
RunAsync(). ContinueWith(tsk => { if(tsk.IsFaulted) throw tsk.Exception; // do something UI specific }, TaskScheduler.FromCurrentSynchronizationContext());
If you don’t like the exception code mixed with the non-exception you could ofcourse create a continuation that is only called when a fault is detected, using TaskContinuationOptions.OnlyOnFaulted
This will correctly handle the exception and throw it, but you’ll probably find it just seems to disappear after the throw and doesn’t even appear in the various unhandled exception handlers – meaning the worse case occurs for an exception, in that it simply disappears.
What we really want is to throw the exception onto the Dispatcher thread so that an unhandled exception handler can at least alert the user that a problem exists. We can do this using the following line of code
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => { throw ex; }));
Now, unfortunately this means the stack trace is lost as we’re not simply re-throwing the original exception, but on the plus side we now actually see the exception.