Introduced in C# 5 async/await keywords significantly simplify asynchronous code and improve code readability and maintainability. However, when it comes to exception handling, it becomes a bit trickier.
Let’s consider the following example:
static void Main(string[] args)
{
try
{
AsyncMethod();
}
catch
{
Console.WriteLine("Exception in Main");
}
Console.ReadLine();
}
private async static void AsyncMethod()
{
throw new NotImplementedException();
}
When executed, instead of displaying “Exception in Main” message, this program crashes. Similar to this console application, all exceptions raised from async void methods crash Windows 8 apps too.
In console and desktop programs unhandled exceptions can be intercepted using AppDomain.UnhandledException
event. Only intercepted, for example for logging - it doesn’t prevent crash of the program. In Windows 8 apps even interception is not possible because AppDomain
is not part of .NET profile for Windows Store apps.
Windows 8.1 changes the way the async-related exceptions are handled. Now it is possible to catch exception raised from async void method by handling Application.UnhandledException
event:
sealed partial class MyApp : Application
{
public MyApp()
{
this.InitializeComponent();
UnhandledException += Application_UnhandledException;
}
private void Application_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
e.Handled = true;
// ...
}
}
With UnhandledException
event it is possible to not only log exception but also prevent process termination (e.Handled = true
).
The following example demonstrate code that will behave differently in Windows 8 and Windows 8.1:
private async void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
throw new NotImplementedException();
}
In Windows 8 it will raise exception and terminate process, without possibility to catch it using Application.UnhandledException
event. In Windows 8.1 Application.UnhandledException
event will be fired in case of such exception.