Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using an Async Action to Run Synchronous Code

I have a search action that has two paths, a synchronous path, that just returns a simple view, and a asynchronous path, that does the search asynchronously and then returns a view. Both are GET requests, so they are part of the same action.

The problem is that when I access the action "localhost:XXXX/Home/Search", the page just infinitely loads. Using Fiddler, I can see that the request never returns. I've debugged it and it makes it to the last line of code, but, again, the request doesn't complete.

I've simplified the repro to the following:

public async Task<ActionResult> Search() 
{ 
    return View(); 
} 

VS11 warns me that the code will be run synchronously without an await, which is fine, but the request doesn't complete.

Should this work? Or do I need to do something else here?

Edit

This is MVC 4 targeting .NET 4.5.

Edit 2

For those who see things better in code, this is why I need synchronous in an async action:

public async Task<ActionResult> Search(string query = null)
{
    if (string.IsNullOrWhiteSpace(query))
        return View(new SearchViewModel());   // never loads

    var model = await _someService.SearchAsync(query);
    return View(model);    // loads
}
like image 783
Dan Friedman Avatar asked Mar 09 '12 00:03

Dan Friedman


People also ask

Does async function run synchronously?

Top-level code, up to and including the first await expression (if there is one), is run synchronously. In this way, an async function without an await expression will run synchronously. If there is an await expression inside the function body, however, the async function will always complete asynchronously.

What is the preferable way to run async code synchronously?

The best answer to the question "How can I call an async method synchronously" is "don't". There are hacks to try to force it to work, but they all have very subtle pitfalls. Instead, back up and fix the code that makes you "need" to do this.

Does async await make code synchronous?

Async/await helps you write synchronous-looking JavaScript code that works asynchronously. Await is in an async function to ensure that all promises that are returned in the function are synchronized. With async/await, there's no use of callbacks.

Can we call synchronous method from another asynchronous method?

Yes, We can call a synchronous method inside a future method. Both will run on Asynchronous Only.


1 Answers

This is a known bug in the beta. To quote Stephen Toub:

The short answer is that there is a known bug in ASP.NET MVC in the .NET 4.5 Beta that results in this issue when the async method completes synchronously. Until a fix is available, a simple workaround is to add "await Task.Yield();" as the first line of the async method, forcing it to complete asynchronously. For this to work correctly, you also need to ensure you're using the new SynchronizationContext supplied by ASP.NET in .NET 4.5, which means ensuring you have the line:

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />

in the appSettings section of your configuration file.

like image 93
Stephen Cleary Avatar answered Sep 28 '22 08:09

Stephen Cleary