Task<ActionResult> not returning for cases when no await is required.


Hi There,

I'm experiencing the following the issue with using the new async, await functionality in ASP.NET MVC.
When for example the controller action only performs an await in certain cases, in the cases where the await does not execute, the view never returns to the browse and it simply keeps trying to load indefinitely.
Below is a Sample Controller Action to demonstrate:

    // GET: /Development/Example

    public async Task<ActionResult> Example()
        //When IsLoaded is set to true, this view is never returned to the browser.
        Boolean IsLoaded = true;
        if (!IsLoaded)
            //Perform a time consuming operation that requires an await here, when IsLoaded is false.
            //For example remote data must be read because it has not been loaded.
            await Task.Run(() => { System.Threading.Thread.Sleep(100); });

            //If However IsLoaded is true, the time consuming operation does not have to be performed.
            //For example the remote data has already been loaded.

        //Finally return a View as usual
        return View();

I'm not sure if this is the expected behavior (Or I am not understanding correct the usage of the async, await functionality ) and if so guidance relating to how I should get around this would be hugely appreciated?
I tried reproducing it in a Win Forms application using async and await and I couldn't get it to go wrong there, so that's why i'm posting here.
Currently as a work around I have added a Task.Run(() => { System.Threading.Thread.Sleep(1); }); to mimic an await operation when no other wait is performed however this is far from ideal.

Thanks for your time!

Closed May 4, 2012 at 12:14 AM by bhaveshc
Repro'ed the issue in Beta and verified that it's fixed in the current code.


BradWilson wrote Apr 2, 2012 at 7:46 AM

Thanks for reporting this bug. This has already been fixed in the source code, and should be part of the next preview release.

If you need an immediate workaround, you can add the following as the first line to your controller action:

await Task.Yield();

This will ensure that your controller always spins up a task on a new thread. Once the next preview is available, this workaround should no longer be necessary.