Jason King Team : Web Development Tags : Web Development

Async void….don’t use it!

Jason King Team : Web Development Tags : Web Development

Recently I was asked to investigate a bug where an InvalidOperationException was being thrown with the message “An asynchronous module or handler completed while an asynchronous operation was still pending.”  

I found the section of code that was causing the error.   It was a simple asynchronous action on an MVC controller.   A method that was called by the action had recently had it’s signature changed from:

public void Invite()

to:

public async void Invite()

 

I was quite surprised that the compiler didn’t warn about the mistake.

 

Here is a complete example that shows the error:

public async Task<ActionResult> DoSomething()
        {
            await Task.Delay(100);
            this.AsyncVoidMethod();
            return Json(new { success = true });
        }
 
        private async void AsyncVoidMethod()
        {
            await Task.Delay(100);
        }

If you navigate to /controller/DoSomething you’ll get a yellow screen of death with the InvalidOperationException exception.

The method signature is valid as asynchronous event handlers need to return void however all other asynchronous methods should either Task or Task<T>.   Without returning Task it’s impossible for the calling method to know when the asynchronous method has completed.

Change the second method to:

private async Task AsyncVoidMethod()
        {
            await Task.Delay(100);
        }

The compiler now warns that the method is not awaited by the caller.

So the lesson here is be very careful about using async void as you nearly always should be writing async Task.

Here is a great article explaining the problem with async void methods in detail: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx