2

I suppose, there is a thread pool which the web server are using to serve requests. So the controllers are running within one of the thread of this thread pool. Say it is the 'serving' pool.

In one of my async action method I use an async method,

var myResult = await myObject.MyMethodAsync();
// my completion logic here

As explained many places, we are doing this, to not block the valuable serving pool thread, instead execute MyMethodAsync in an other background thread... then continue the completion logic in again a serving pool thread, probably in other one, but having the http context, and some othe minor things marshaled there correctly.

So the background thread in which MyMethodAsync runs must be from an other thread pool, unless the whole thing makes no sense.

Question

Please confirm or correct my understanding and in case if it is correct, I still miss why would one thread in one pool more valuable resource than other thread in another pool? In the end of the day the whole thing runs on a same particular hardware with given number of cores and CPU performance...

3
  • There are a limited amount of threads available to serve requests. If your logic is executed on these threads they are unavailable for other requests. When working async you work on another thread from another pool so the request thread is available again to serve other requests. Commented Feb 17, 2023 at 6:05
  • OK, but at the and of the day the server hw also has a particular limited capacity, so what is the use to split the thread to two pools? Commented Feb 17, 2023 at 6:10
  • Being able to serve more requests at once. I will link the following (as this question is already asked before) with more info: should I use async await. And yes hardware is also a limit for performance and with good software/code we utilize the hardware as best as possible Commented Feb 17, 2023 at 6:17

1 Answer 1

6

There is only one thread pool in a .NET application. It has both worker threads and I/O threads, which are treated differently, but there is only one pool.

I suppose, there is a thread pool which the web server are using to serve requests. So the controllers are running within one of the thread of this thread pool. Say it is the 'serving' pool.

ASP.NET uses the .NET thread pool to serve requests, yes.

As explained many places, we are doing this, to not block the valuable serving pool thread, instead execute MyMethodAsync in an other background thread... then continue the completion logic in again a serving pool thread, probably in other one, but having the http context, and some othe minor things marshaled there correctly.

So the background thread in which MyMethodAsync runs must be from an other thread pool, unless the whole thing makes no sense.

This is the wrong part.

With truly asynchronous methods, there is no thread (as described on my blog). While the code within MyMethodAsync will run on some thread, there is no thread dedicated to running MyMethodAsync until it completes.

You can think about it this way: asynchronous code usually deals with I/O, so lets say for example that MyMethodAsync is posting something to an API. Once the post is sent, there's no point in having a thread just block waiting for a response. Instead, MyMethodAsync just wires up a continuation and returns. As a result, most asynchronous controller methods use zero threads while waiting for external systems to respond. There's no "other thread pool" because there's no "other thread" at all.

Which is kind of the point of asynchronous code on ASP.NET: to use fewer threads to serve more requests. Also see this article.

Sign up to request clarification or add additional context in comments.

10 Comments

Many thx for your detailed answer. It seems you dealt with this very question 10 years before in your blog. It also seems you had to argue on this many times, even before you wrote your blog, hence the tone... Anyway, the OS async IO and a modern OS behavior to spare its resources is pretty well known to professionals. However I found weak point of the whole argument is the cloudy definition of "truly asynchronous"...
...If that async method written by a developer in C#, using the Task library (either you, either me, or an open source third party library or even in MS Team), then will be a prolog, epilog code which must be run in a particular thread. var i = 0; within an async method will not be run in the thin air... OK, I understand this method is not a "truly asynchronous" method instead a hybrid of executable C# statements mixed with one or more further async method calls, which are also may "truly async" or hybrid and so on... So what about those async methods in real life?
I did not mean to have an argumentative tone at all; I never mind explaining things. Code statements are run on threads; see my async intro for details on which thread(s) are used. By "truly asynchronous", I mean methods that have a point where there are no threads being used. This is in contrast to methods that are synchronous (always returns a completed task) or "fake asynchronous" (just runs synchronous code on a thread pool thread).
As explained on my blog, async methods begin executing on the calling thread until they hit an asynchronous await, at which point there is no thread. Later, they continue executing on the SynchronizationContext or TaskScheduler that was current at the time of the await.
@NguyenTran: Yes, it can be another thread. This is problematic if you use ThreadStatic, but AsyncLocal will work correctly.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.