We all know the famous blog post regarding blocking on async code by Stephen Cleary. In MVC 5 the following code deadlocks when requesting Home/Index
:
public class HomeController : Controller
{
public string Index()
{
var model = AsyncMethod();
return model.Result;
}
private async Task<string> AsyncMethod()
{
await Task.Run(() => Thread.Sleep(2000));
return "Hello";
}
}
However, the exact same code doesn't deadlock in an MVC Core web application. The response returns Hello. Why? Does MVC Core allow multiple threads to run simultaneously within one request context? Is the Don't Block on Async Code phrase out of date when developing in MVC Core?
Why?
ASP.NET Core is async
from top to bottom, and it's designed for maximum speed.
As part of the redesign, the ASP.NET team was able to remove the entire AspNetSynchronizationContext
completely. Some aspects of the ASP.NET request context were moved into the core .NET, and others were just dropped (e.g., HttpContext.Current
).
Does MVC Core allow multiple threads to run simultaneously within one request context?
No. The notion of a "request context" is no longer represented by a synchronization context, though.
Is the Don't Block on Async Code phrase out of date when developing in MVC Core?
No. It won't deadlock on ASP.NET Core, but you still shouldn't do it.
"Can I block on async code in MVC Core?" Yes. "Should I block on async code in MVC Core?" No.
This code
await Task.Run(() => Thread.Sleep(2000));
might not be a great pattern, but it's not "blocking" in the same sense that Stephen's post refers to. To compare apples to apples, you'd have to do this:
private string BlockingAsyncMethod()
{
Task.Run(() => Thread.Sleep(2000)).Wait();
return "Hello";
}
Blocking on Wait()
or .Result
is the big no-no for MVC 5. To my knowledge, that is still correct advice for MVC Core.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With