Remix.run Logo
▲ fodkodrasz 41 minutes ago

the main problem with the .net async/await is the immediate execution of a call returning a Task, without control over where it may execute. F#'s asnyc was way saner and easier to understand in my opinion.

I'd beg to differ on the easy to understand... last time i worked with this stuff like ConfigureAwait only has cargo cults and no real good explanation, and wasn't covered in any recent version of eg. CLR via C#... Distributed tracing and thread management were totally bitten by async, also the way iterators and LINQ were broken... that was when I got off the train, as it broke the best abstractions for line of business code so that instead of designing an IO pipeline lazy developers could simple put Task.Run around blocking IO calls at the bottom of the codebas, and ... yeah, we are back at function coloring.

This brings me to: I winder for what kind of apps did you find it a delight, because for extensive data wrangling leveraging multiple calls it was a pain.

▲fabian2k 37 minutes ago | parent [-]

You don't need ConfigureAwait() at all in modern C# (unless you're writing desktop UI code, I don't know enough about that to comment there). In a modern ASP.NET Core web application you don't care about which thread your Task executes, there is no synchronization context at all.

I'm using C# for the backend of a web application, not legacy but .NET Core from the start.

▲fodkodrasz 21 minutes ago | parent [-]

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 17 minutes 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.