I've asserted my understanding of async/await on a couple of occasions, often with some debate as to whether or not I'm correct. I'd really appreciate it if anyone could either confirm or deny my understanding, and clear up any misconceptions so that I don't spread misinformation.
High-Level Understanding
async
/await
is a way of avoiding callback hell while writing asynchronous code. A thread that is executing an asynchronous method will return to the thread pool when it encounters an await
, and will pick up execution once the awaited operation completes.
Low-Level Understanding
The JIT will split an asynchronous methods into discrete parts around await
points, allowing re-entry into the method with method's state preserved. Under the covers this involves some sort of state machine.
Relation to Concurrency
async
/await
does not imply any sort of concurrency. An application written using async
/await
could be entirely single-threaded while still reaping all the benefits, much the way that node.js does albeit with callbacks. Unlike node.js, .NET is multi-threaded so by having async
/await
, you get the benefits of non-blocking IO without using callbacks while also having multiple threads of execution.
The Benefits
async
/await
frees up threads to do other things while waiting for IO to complete. It can also be used in conjunction with the TPL to do CPU bound work on multiple threads, or off the UI thread.
In order to benefit from non-blocking IO, the asynchronous methods need to be built on top of API's that actually take advantage of non-blocking IO which are ultimately provided by the OS.
Misuse
This is the biggest point of contention in my understanding. A lot of people believe that wrapping a blocking operation in a Task
and using async
/await
will bring about a performance increase. By creating an additional thread to handle an operation, returning the original thread to the thread pool, and then resuming the original method after the task completes, all that's occurring are unnecessary context switches while not really freeing up threads to do other work. While this isn't as much a misuse of async
/await
as it is the TPL, this mindset seems to stem from a misunderstanding of async
/await
.