I think it is a very good question and also very hard to answer it especially in the case of a web site.
I've had a bit of confusion to do with exactly what the web service should send back to the client website'
The most important thing to understand if you use async/await, then your action method code still serialized, I mean the next line will be executed only after the async operation finished. However there will be (at least) three threads:
- To original web server worker thread in which the action method is
called. Originally the MVC infrastructure got this thread from the
pool, and dedicated this thread to serve the current request.
- Optional thread(s) what are started by the async operation what can
be called with await.
- A continuation thread (also a worker from the
pool) in which your action method is continuing after the await. Note
this thread will have the same context (HttpContext, user culture
etc) what was the original worker so it's transparent for you, but it will be an other thread freshly allocated from the pool.
For the first sight it has no sense: Why all those thread hocus-pocus in case if the operations in the action method are still serialized? I takes the same time... To understand this we must take a look to a desktop application say a WPF app.
To be short: There is a message loop and a dedicated thread which reads the UI (and other virtual) events from a queue and executes the event handlers in the context of this thread, like a button click event. In case you block this thread for 2 second the UI will be unresponsive for that time. So that's why we would like to do many things in async way in an other thread, and let the dedicated (UI) thread to fast return and process other messages from the queue. However this could be very inconvenient, because we sometime wanted to continue something after the async operation ended and we had the result. The C# feature async/await made this very convenient. This case the continuation thread is always the dedicated UI thread but in its (very) later round in its endless loop. To wrap it up:
In an event handler you can use async/await to still execute your operations in serialized, the continuation will be done always in the original dedicated UI thread but during the await this thread can loop, and process other messages.
Now back to the MVC action method: In this case your action method is the analogy of the event handler. Although it is still hard to understand the use of the thread complication: This case blocking the action method would not block anything (as it blocked the dedicated UI thread in WPF). Here are the facts:
- Other clients (browsers) requests will be served by other threads. (so we are
not blocking anything by blocking this thread (*) keep reading
- This request will not be served faster even if we use async/await because
the operations are serialized and we must wait (await) the result of
the async operation. (Do not confuse async/await with parallel processing)
So the use of async/await and the transparent thread tricks is not so obvious as it was in the case of the desktop application.
Still: Pool is not an endless resource. Releasing ASAP back to the pool (by await) the worker thread what was originally dedicated to serve the request, and let continue in an other thread after completion the async operation may lead better utilization of the thread pool and may lead better performance of the web server under extreme stress.