DEV Community

Discussion on: .NET Threading Gotchas

Collapse
 
cajuncoding profile image
cajuncoding • Edited

Nice Article, and very useful topic for alot of developers . . . so thanks for posting it.

However, I think that the first example confuses is #async with #threads a little too much.... somethign that will lead many deveopers to an incorrect understanding of what Async/Await is really for.

Based on the naming convention of 'Async' in the method names, it implies that these are I/O constrained methods and therefore the code sample is not correct.

It uses Task.Run() to wrap what are already Async methods that will always return a Task; in many cases this is incorrect. So this statement is only partially valid: "Think about it this way: in an async operation, you need to spin up a new thread, wait for the thread to start, and then rejoin the original call."

When working with Async/Await you MUST ALWAYS consider if the code logic is I/O constrained (e.g. depending on some external systems performance/response), or CPU constrained (e.g. depending on the internal CPU/Memory performance/limitations).

So if the method 'PlotDominationAsync' was in fact a REST API call (e.g. I/O constrained) then wrapping it in Task.Run() is a complete waste of a Thread from the thread pool, and an incorrect way to write this code. If however it was all computationally (e.g. CPU constrained) constrained, then yes spinning up another thread will allow multi-processor system to leverage another core to handle the work in parallel -- but with the side effect of consuming even more server resources; for example: potentially limiting the scalability of a web server.

Based on the naming convention of "Async" it implies that these are all I/O constrained so the correct code is this (which has NO additional thread overhead) and will 100% always be a better way to go because it will allow all 4 external systems to do their work in parallel, while actually RELEASING the current application thread to go do something else useful!

await Task.WhenAll(new List<Task>() {
     PlotDominationAsync,
     DeployTroopsAsync,
     EstablishEvilHeadquartersAsync,
     LaunchDeathRayAsync
}
Collapse
 
integerman profile image
Matt Eland

Thank you for your detailed writeup / response. I love posting things like this because the folks who have drilled deep can help me understand misconceptions I didn't even know I had.

I'll make the edit later today, but I appreciate you taking the time to respond.

Collapse
 
bernarddusablon profile image
Bernard Dusablon

Seriously the most complete and comprehensive article on the subject, including the feedback of rearea1616. It definitely clarify the concept! Thank you very much!