I quote "Awaiting asynchronous code, two things happen. A thread is taken from the thread pool and allocated to the asynchronous operation".
That's just wrong and a big misunderstanding of async/await. Asynchrony doesn't need to get threads from the thread pool or otherwise.
In your case it just happens because you used Task.Run but that's a edge case and actually not a good practice with async/await (Task.Run is more suited with TPL but you can use async/await when you combine with other asynchronous calls). Most asynchronous code never consumes threads.
That said I did enjoy reading the article. But that's because I'm evil!
Hi, I appreciate your comment - and you are partially correct.
It's up to the scheduler to determine if a new thread is needed. It may or may not spin up a new thread. I'll clarify it when I have a chance.
It is a bit more than that actually. Your example demonstrates parallel computation not asynchrony. Task.Run never creates asynchronous code, whether the scheduler decides to run it immediatly on the same thread, or to schedule it on a worker.
It is understandable to be confused since most of us (me included) started to use tasks when async/await got out. But the Task type was originally created for parallel computing with the TPL (hence why it is in a System.Threading sub-namespace). Asynchronous task (also called future or promise in other languages) should have used a different type but the .Net team decided to reuse Task for that purpose. It does lead to a unified model where we can combine both, but it also adds to the confusion.
I think a better example would be to use sockets or file asynchronous reading/writing, which doesn't involve any threads.
Thanks for the explanation (and the link) Nicolas :) you really taught me something valuable today.
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.