2

Imagine this action:

public async Task<ActionResult> MyAction(){
    var result = await MyMethodAsync();
    return View(result);
}



I understand that by making the action async, you release the thread executing the action back to the thread pool while MyMethodAsync() executes, so that it can be used to serve other HTTP requests.

Now I'm wondering: then what thread executes MyMethodAsync()? I'm guessing it's not another thread from the thread pool, since that would defeat the purpose of async actions. Is it just a brand new thread that is created, started and destroyed when the HTTP response is finished?

AxiomaticNexus
  • 6,190
  • 3
  • 41
  • 61

1 Answers1

3

No it still comes from the thread pool, and it does not defeat any purpose.

Async comes becomes valuable during blocking operations, like accessing the disk or network, anything that is not cpu-bound (i.e., operations that are I/O (Input/Output) bound).

The thread is returned to the pool only so that it doesn't have to wait for the blocking operation to complete before it can help service another HTTP request.

Once the blocking operation is complete, another worker thread is grabbed from the pool.

This can help to counteract something called thread pool starvation. Each thread pool only spins up so many threads, and spinning up more is expensive. Sometimes it is the case that a web server can be tied up with many threads waiting for blocking operations to complete, so new requests have to wait for a new thread, meaning they have to wait for someone else's blocking operation. With async, a thread that is waiting on a blocking operation can be returned to the pool so that it can service other (possibly CPU-bound) requests.

Read this: http://msdn.microsoft.com/en-us/library/ee728598(VS.100).aspx

...and then read this: http://blog.stephencleary.com/2013/11/there-is-no-thread.html

I understand that another thread is grabbed from the pool once the blocking operation is done, but what I don't know is exactly what thread executes the blocking operation itself.

No thread executes the blocking operation. The CPU is waiting on another device -- like the network card, or the disk controller, to return output.

Threads are CPU-bound artifacts, as is RAM, since it operates over a buss according to the CPU clock rate. There are other devices in the machine like USB, network card, disks, etc. These other devices are I/O bound because they are input/output devices.

danludwig
  • 46,965
  • 25
  • 159
  • 237
  • I understand that another thread is grabbed from the pool once the blocking operation is done, but what I don't know is exactly what thread executes the blocking operation itself. – AxiomaticNexus Oct 23 '14 at 01:11
  • 1
    +1. I was going to add a similar answer, but you beat me to it and yours was going down a better path anyway! – Justin Helgerson Oct 23 '14 at 01:13
  • On the .Net level, doesn't a thread have to wait/block for the network card or disk controller to return output? – AxiomaticNexus Oct 23 '14 at 01:19
  • @YasmaniLlanes even if a thread did have to wait/block, it would not be an IIS thread, it would be a kernel thread, with a totally different set of resources to maintain track of. – danludwig Oct 23 '14 at 01:22
  • @danludwig I think I understand. The answer lies in the lower levels of the framework, in dark rooms that I don't really have to look into :-) – AxiomaticNexus Oct 23 '14 at 01:27
  • @YasmaniLlanes - "lower level" yes, all the way down to the device drivers. It's typically the kernel that ultimately manages access to I/O-bound hardware. – danludwig Oct 23 '14 at 01:36
  • 1
    @YasmaniLlanes: I have a [blog post that explains it](http://blog.stephencleary.com/2013/11/there-is-no-thread.html). – Stephen Cleary Oct 23 '14 at 12:15