Exceptions from Awaitable Code


Throwing an Exception on another ‘native’ thread has always been difficult to catch and manage. Sometimes, it was really easy to lose the all important stack trace for your post-production tracing. Fortunately, C# 5.0 has you covered.

The new C# await keyword - and its cousin, the async keyword - is nothing short of awesomeness! If multi-threading got any easier, it would be like microwaving left overs and calling it dinner, but I digress.

I put a quick sample together on Github to demonstrate when an exception is thrown from your long running task, it would print out the stack trace and exactly who caught it.

Below is the output from running the sample.

DoAsyncOperationAndWait() method:
System.Exception: Hello there!
   at ExceptionsFromAwaitableCode.Program.<DoAsyncOperationAsTask>b__3() in c:\Source\Personal\Examples\ExceptionsFromAwaitableCode\ExceptionsFromAwaitableCode\Program.cs:line 43
   at System.Threading.Tasks.Task`1.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at ExceptionsFromAwaitableCode.Program.<DoAsyncOperationAndWait>d__0.MoveNext() in c:\Source\Personal\Examples\ExceptionsFromAwaitableCode\ExceptionsFromAwaitableCode\Program.cs:line 30

And here is the code:

static void Main(string[] args)
{
	try
	{
		DoAsyncOperationAndWait().Wait();
	}
	catch(Exception ex)
	{
		Console.WriteLine("Main() method:");
		Console.WriteLine(ex);
	}

	Console.ReadKey();
}

private static async Task DoAsyncOperationAndWait()
{
	try
	{
		await DoAsyncOperationAsTask();
	}
	catch (Exception ex)
	{
		Console.WriteLine("DoAsyncOperationAndWait() method:");
		Console.WriteLine(ex);
	}
}

private static Task DoAsyncOperationAsTask()
{
	return Task.Run(() => { throw new Exception("Hello there!"); });
}

So what does this mean? The exception can be caught from the async method. And that is a good thing that an Exception does not get swallowed up.

blog comments powered by Disqus