Remix.run Logo
▲ fodkodrasz an hour ago

Sometimes you do care where it executes, and then it starts to become a problem ;).

Something which was as easy as an IO call in the middle of a function running on a thread pool becomes a PITA if the IO call is cleverly async-ized (by wrapping the original sync IO method into a Task.Run(), but actually this is the better case!) ad then removed from the public API... (cannot recall the exact library, but it was a pain, as it was some core stuff, maybe vendored by MS themselves)

Also back then it caused us loosing correlation IDs as those were thread locals in traditional pre-async ASP.Net Core (think version 0.9-2.0 when I worked on that part, then up until core 4 and the async mania continuos broke readable calculation code in LINQ, TPL based performant data pipelines, etc...) and with async execution started to migrate between threads... If you needed high performance you already used threads, because it was not a classic web application, but a specialized optimization algorithm with a web api... and if you need more than CRUD, and use all the cores (and SIMD) to squeeze out all performance you have, you hit these problems right away. These all could be solved, but it actually broke stuff, a lot of stuff, as developers jumped on the fad, and it their sync code was turned into a .ConfigureAwait(false /* Microsoft blogs talk a lot about it without a clear explanation, so every cool kid does this */).GetAwaiter().GetResult()... then you some of your threaded code silently broken if you dare used Thread Locals... Faded memories, but that was when they f'ed up the C# language.

▲fabian2k an hour ago | parent [-]

That's why I emphasized modern .NET. All I/O should be using async methods through the entire application. Wrapping sync code in async causes troubles, but that is entirely avoidable in new code. That's the price you have to pay to make this particular abstraction work well, everything I/O must be async.