Async is a goto state machine. While the IO is set as blocked at the operating system level, it does something else. Then when it's unblocked, it jumps back.
I'm still having a hard time with async. I see lot's of async code using Tasks, pretty much 99% of the time. Wouldn't this make async code using threads anyway?
Async code, down in the "guts" of the system, will borrow user-level and OS-level threads, so while it's correct that it does use threads, it won't spawn off new ones. Spawning off a new thread ultimately wouldn't accomplish much (after all, why not have IIS just use a new one?).
I like to think of it as utilizing the operating system more efficiently. I/O on a system is asynchronous by default. Async code will essentially delegate work so the OS can do what it does best!
Async is a goto state machine. While the IO is set as blocked at the operating system level, it does something else. Then when it's unblocked, it jumps back.