Did you ever wonder why you should use async
and await
in your ASP.NET Core applications? Most probable 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).ConfigureAwait(false);
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 ?
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 SQL Server
which 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. Obvious 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 which only has 1 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 it, but it also shows the power of async and await. Instead of not being able to serve all request, we are not 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!
Top comments (1)
Good stuff, thanks. Couple of notes here.
ConfigureAwait()
. No synchronization context means that awaited calls resume using the TPL's task manager, which is exactly whatConfigureAwait(false)
is supposed to do.