Posted by Filip Ekberg on September 20 2012 6 Comments
Since the release of .NET 4.5, you’ve been able to use the RTM version of Async & Await. There are some things though that can lead to very weird behaviors in your applications, and a lot of confusion. Kevin (Pilchie) over at Microsoft just gave me heads up on some of these and I thought that I would share it with the rest of you!
When you’re doing asynchronous methods that just return void, there is no way to track when these methods are done.
Look at the following example:
public async void Biz()
public Task Foo()
return Task.Factory.StartNew(() =>
If we create an instance of
FooBar and call
Biz(), there’s no way for us to wait for the task to finish. Normally we would want a reference to a
Task that we could wait for to finish, but in this case we don’t! Avoid
async void whenever you can.
Just change the method signature to
async Task instead and you will be able to do:
The only reason you want to use
async void is when you have an event handler that needs to
await something. Such as a
Click event handler like this:
var task = Task<string>.Factory.StartNew(() =>
var data = await task;
Never getting that second exception when awaiting multiple results?
Consider that we have two asynchronous methods that both thrown an exception (almost at the same time), like these two methods here:
What would happen if we called the following method?
return await Foo() + await Bar();
We would indeed get an exception thrown. But we would only get One exception thrown! In fact, the only exception that we will get is the First exception being thrown.
This means that we would not see an aggregated exception list as we might expect.
Tasks don’t travel back to the caller
When working with multiple threads and the thread causes a problem that is unhandled, these are thrown back at the caller.
Look at this following example for instance:
When running this, we will see the following exception:
Unhandled Exception: System.Exception: Exception of type ‘System.Exception’ was thrown.
This is perfectly reasonable, it tears down the calling process!
But what about if this was a
The following code spawns a new task and just throws a similar exception to what the thread example did above:
What happens when we run this? Nothing!
No exception were traveled back to the caller, this can cause potential confusions. This is actually by design and MSDN says the following about it:
In the .NET Framework 4, by default, if a
Taskthat has an unobserved exception is garbage collected, the finalizer throws an exception and terminates the process. The termination of the process is determined by the timing of garbage collection and finalization.
To make it easier for developers to write asynchronous code based on tasks, the .NET Framework 4.5 changes this default behavior for unobserved exceptions. Unobserved exceptions still cause the
UnobservedTaskExceptionevent to be raised, but by default, the process does not terminate. Instead, the exception is ignored after the event is raised, regardless of whether an event handler observes the exception.
If we want the the .NET 4 behavior, we can re-enable the unobserved task exceptions by changing the applications app.config. Add the following to the app.config:
Since the exception will be thrown in the finalizer, we can test this by running the following:
This will tear down the process as it did in .NET 4.0.
Unhandled Exception: System.AggregateException: A Task’s exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. —> System.Exception: Exception of type ‘System.Exception’ was thrown.
Have you ever shot yourself in the foot with Tasks or Async? Leave your horror stories in the comment field!