Did you ever wonder why you "should" use async
and await
in your ASP.NET Core applications? Most probably, you heard something about performance. And there is some truth to it, but not in the way you might think.
Have a look at the following asynchronous controller code:
[HttpGet]
public async Task<IActionResult> GetByIdAsync(int id)
{
var entity = await repository.GetByIdAsync(id);
return Ok(entity);
}
And here the "sync" version of it:
[HttpGet]
public IActionResult GetById(int id)
{
var entity = repository.GetById(id);
return Ok(entity);
}
They look pretty much the same, so Why should I prefer the async version here even if it seems more complex?
The answer is not performance, as in it runs faster. The answer is: It scales better. Let's dissect the synchronous version for a moment. When we hit repository.GetById(...)
, the current worker thread stops and has to wait until the job is done. Most likely, you have a DocumentDb or SQL Server that does the real work. And these are not even local. They are on a different machine, so your server is literally idling until the answer comes back. Once this happens, your controller returns.
Now let's check the async version: Here, we also have to wait for the repository to finish its stuff, but there is a key difference. The await
keyword allows the current worker thread to "detach" from the program and go back to the thread pool. Once GetByIdAsync
is done, .NET will take another thread from the pool and continue the work.
Now, the runtime will be the same. Obviously, it could even be that the async version is slightly (in the sense of measurable but not important) slower. But we return the thread to the thread pool and pick it up once the async stuff is finished. This is important for one thing: Scalability.
You see everytime you make a request against your server, a new worker thread will process your stuff. When you return the thread, when it just idles around, you can utilize that thread to make process another request. That is why async
and await
are powerful in combination with ASP.NET Core.
Another small example: Imagine you have a server that only has one available worker thread in the pool. Also two requests are coming in shortly one after another. In the synchronous version only the first request can be dealt with as there are no free threads available anymore. In the asynchronous version the second request can be immediately handled once the first request reached to the await repository.GetByIdAsync(...)
line. The second request also encounters this line and returns that one thread back to the pool, which immediately gets picked up by request 1 to return the answer. Later we can then return the answer for request 2.
Sure, this is a made-up scenario, which I hope you don't run into, but it also shows the power of async and await. Instead of not being able to serve all requests, we are now able to, even though it might take a bit longer.
Conclusion
Asynchronous programming in ASP.NET Core is a super efficient way of scaling your web application. You can fully utilize your server and system resources are not just idling around!