DEV Community

Discussion on: How C# asynchronous programming is different than what you think

Collapse
 
rhymes profile image
rhymes • Edited

async/await uses no threads, you can imagine it as a call-back. (this is a more detailed explanation)

are you sure? I'd agree normally but in this article I found on MSDN: Task-based asynchronous pattern (TAP) and Async in depth linked from Async overview they clearly talk about async tasks mapped on a thread pool.

@vekzdran also linked article ASP.NET Core SynchronizationContext which talks about thread pooling again.

But probably we're talking about two slightly different things due to my lack of familiarity with .NET and C#.

async/await by themselves don't introduce threads, but ASP.NET uses async on top of a pool to handle concurrent requests? Is that the source of my confusion?

Since no threading is used with async/await, it's mainly meant for IO-bound operations (threads still have their place in CPU intensive operations.)

I read this in the article you linked:

The async and await keywords don't cause additional threads to be created. Async methods don't require multithreading because an async method doesn't run on its own thread. The method runs on the current synchronization context and uses time on the thread only when the method is active. You can use Task.Run to move CPU-bound work to a background thread, but a background thread doesn't help with a process that's just waiting for results to become available.

I'm a little confused by the paragraph you linked. What this paragraph says to me is that calling await something does not generate a thread (which makes sense, otherwise every call would create its own thread and add a lot of context switching). But it doesn't exclude the fact that an async operation MIGHT be running on a different thread than the one it was called from (which is compatible with the idea of pooling, see what happens in Go with goroutines which are transparently mapped on a pool of threads). As it says, if you have a CPU intensive operation (perhaps blocking the context switch of the continuations) you can explicitly tell the compiler to move the operation to a background thread. So yeah, from what I've gathered by this and the other articles thread pooling MIGHT be involved or not, it's just not visible to the programmer (which is why it's a great implementation).

we got a heck more reliable and faster mail sending, and I've never heard any user complaining about his verification email after!

Yeah, putting a queue between you and the SMTP server was a good idea :)
You might want to follow Christine Spang if you're still interested in all things "Python + email":

spang image
Thread Thread
 
yaser profile image
Yaser Al-Najjar

My rule of thumb is:

  • If I want nonblocking code that is related to IO (say talk to db) without creating a thread, I simply throw async/await everywhere.

  • If I want to create a thread to do some cpu heavy computation, I add Task.Run and fill in the lambda my sync code (and for sure that requires adding async/await).

This is the way I do async C#... I should say I never tried to check those statements 😁

Also, some operations might lead the OS to create a thread, but that doesn't count on our app process (it's the way the OS does its business instead).

Thanks for the recommendation, I just read her posts and they seem interesting!