Comment by neonsunset
Comment by neonsunset 2 days ago
Usually dual APIs are offered when they do distinctly different things. Async calls on Socket go through epoll/kqueue via SocketAsyncEngine, which has observably different behavior to regular sockets. There is no such duality in high-level APIs like HttpClient's `.GetStringAsync`.
You are not free from having to worry about it with virtual threads either. If you block a carrier thread with such a low-level API call, the runtime will have a bad time. Or you will always end up paying for a context switch (if you maintain a separate pool of block-able threads).
Green threading UX is better for "regular" code that never bothers to take advantage of concurrency features, but if you do want them, you are quickly back to usually more ceremonious structured concurrency abstractions which, lo and behold, can reimplement the same task system with a worker pool but on top of virtual threads.
If you start to care about cancellation, suddenly you are back to coloring problem regardless. I agree with you that having to write many await's in quick succession is tiresome and unnecessary. It's partially a fault of library authors who name methods "GetSomeLongNameAsync" instead of "Get" or "Query". But other than this it's not as invasive as people make it out to be, and encourages writing highly concurrent code - reducing latency 2x can require moving one or two awaits around. Not so much in Java/Erlang/Go.
I haven't found this is the case many times, many api will have two versions of the api with XxxAsync versions all the way down, maybe less so now days but it took a while to get async entry points added everywhere so you could use it properly, such as ActionResult.ExecuteResultAsync and IAsyncEnumerable as a couple examples.
HttpClient one prime example and you can see the back and forth here internally from MS: https://github.com/dotnet/runtime/issues/32125
This snippet of code or something like it has been used in countless libraries to try and give a workable sync over async which should be baked in: https://github.com/aspnet/AspNetIdentity/blob/main/src/Micro...