News for hackers. Stuff that matters.
Re:.NET 5.0 by jniedrauer on Tuesday November 10, 2020 @01:52PM (#25049655)
> Why would we want that to be synchronous?

Authentication is blocked by accessing storage. You cannot proceed until the storage read operation is completed. There is no parallel work to be accomplished here. This isn't UI code. There's no event loop. Why would you want this to be asynchronous? This seems like async as a dogma, rather than as a tool to accomplish something specific.

Re:.NET 5.0 by manigandham on Tuesday November 10, 2020 @02:40PM (#25050679)
Async means non-blocking, not parallel. It helps keep the app responsive while using less resources and avoiding lockups and crashes.

.NET is used by millions of developers. Strong and scalable foundations matter, and performance is an explicit goal with asp.net being one of the fastest web frameworks. Async is a core part of this.

There's very little - if any - overhead that you need to worry about with async code from the language to Visual Studio.

Re:.NET 5.0 by merb on Tuesday November 10, 2020 @03:26PM (#25051424)
> It helps keep the app responsive while using less resources and avoiding lockups and crashes.

it actually uses more resources. async has a cost, but it is really low.

Re:.NET 5.0 by asyncawaaait on Tuesday November 10, 2020 @04:39PM (#25052338)
There is a resource tradeoff. async/await has a minor CPU/memory impact, but it can also free up threads to do other work during an I/O bound operation.

Threads have their own resource cost.

Re:.NET 5.0 by nullsense on Tuesday November 10, 2020 @02:33PM (#25050562)
>You cannot proceed until the storage read operation is completed.

Exactly. So when you await it, that thread that would have but blocked waiting for the I/O instead can be used to service other requests until the I/O has finished.

Re:.NET 5.0 by ko27 on Tuesday November 10, 2020 @02:45PM (#25050772)
Async is not used just to enable parallel execution. Using 1 thread per every long running request is a good way to bottleneck your web server.
Re:.NET 5.0 by jen20 on Tuesday November 10, 2020 @03:20PM (#25051327)
> There is no parallel work to be accomplished here.

Concurrency is not parallelism [1].

[1]: https://blog.golang.org/waza-talk

Re:.NET 5.0 by jniedrauer on Tuesday November 10, 2020 @04:17PM (#25052054)
Each HTTP request in a Go webserver spawns a goroutine, and there is no need to think about "freeing up threads" since coroutines are not OS threads. There's also no need to leak the word `async` all over your codebase. The problem being solved here with async/await is also being caused by async/await.
Re:.NET 5.0 by oaiey on Tuesday November 10, 2020 @05:47PM (#25053127)
Goroutine like .NET IAwaitable/Task both abstract the thread away. No one thinks about threads when programming async/await code despite in any await keyword a thread change can happen.

Both solve the same problem with the same technique (under the hood it is all the same). One language had the benefit of late birth (go), the other suffers with its friends through a library/language migration (C#, C++, Java, JavaScript, Python, ...). async/await is effectively the modernization of structural programming to benefit from modern concurrency.

Re:.NET 5.0 by jen20 on Tuesday November 10, 2020 @09:49PM (#25055014)
Worth noting that "late birth" is not the only thing at play here - Rust _had_ green threads at one point and removed them - only to add async/await later.
Re:.NET 5.0 by WorldMaker on Wednesday November 11, 2020 @12:38PM (#25060582)
async/await has underpinnings in monadic computation expressions (via F#/Haskell). There are some benefits to the model, despite a lot of its detractors in the thread here. Such as it is possible to work with multiple monads (many languages that support async/await are not strict about which monad they rewrite for; C# supports any Monad that has a GetAwaiter() method of the right shape, JS supports any object with a then() and/or catch() of the right shape, etc).

While async/await is nowhere structurally as capable/composable as for instance Haskell's do notation, it's still more composable than a lot of alternatives and a lot of manual thread management techniques.

The biggest thing though is that these concerns are orthogonal. You can have green threads backing an async/await monad (with some caveats), but you can't as easily swap in anything that follows monad rules into code written specifically just for green threads. (Python makes you explicitly define your threading model before using async/await; the others provide methods to configure it.)

Which is to say "late birth" isn't really a consideration in async/await, it's as much a consideration of flexibility/composition of abstractions. JS, for example, needed that flexibility/composition in the wild west of multiple disparate Promise implementations early on, and may need it again if/when Browsers ever decide to support proper multi-threading whether it is green threads or something else. In such a future you should still be able to compose existing async/await code without modifying it, even as you take advantage of newer threading options.

Re:.NET 5.0 by jen20 on Tuesday November 10, 2020 @09:52PM (#25055029)
The issue is that Go simply does not allow large classes of system which require direct and unfettered access to the operating system primitives to be built.

I'm a huge fan of Go, but pretending the two systems are equivalent either is either disingenuous or belies misunderstanding.

Re:.NET 5.0 by MarkSweep on Tuesday November 10, 2020 @11:13PM (#25055444)
There is sort of an event loop: the .NET Threadpool. It is used by async by default. It will by default quickly create an number of threads equal to the number of CPU cores, but then slowly increase it beyond that. If you are blocking in a threadpool thread, the work item queue will back up. This is called threadpool starvation.

Some articles:

https://docs.microsoft.com/en-us/archive/blogs/vancem/diagno...

https://github.com/Microsoft/vs-threading/blob/master/doc/th...

Re:.NET 5.0 by asyncawaaait on Tuesday November 10, 2020 @02:22PM (#25050364)
Awaiting a storage operation (ie. look up user) in C# will allow other calls to proceed until the I/O is available to read.

Synchronous code locks you into the model of handling one request per thread.

Given the minor overhead (both cognitive and runtime) of a sync/await, I can’t see why you wouldn’t want to do it here.

Re:.NET 5.0 by balfirevic on Tuesday November 10, 2020 @02:31PM (#25050515)
Because async/await infects everything it touches and forces me to spread irrelevant junk words all over the code which have nothing to do with the task I'm trying to accomplish.
Re:.NET 5.0 by hackerfromthefu on Tuesday November 10, 2020 @08:17PM (#25054451)
What about the far worse stack traces and debugging?

Whats a way to get the utility of normal debugging while using async?

Re:.NET 5.0 by asyncawaaait on Tuesday November 10, 2020 @08:31PM (#25054565)
Stack traces were massively improved in 2.1.

Using a good IDE (Rider or Visual Studio), debugging async/await code works as expected.

Are you doing interop or calling unmanaged code?

Re:.NET 5.0 by hackerfromthefu on Wednesday November 11, 2020 @04:44AM (#25056981)
Thanks, I will make sure to check this out. Does anyone have any articles or documentation on this?
Re:.NET 5.0 by benaadams on Wednesday November 11, 2020 @08:17PM (#25065216)
Stacktrace improvements in .NET Core 2.1: Intelligible stack traces for async, iterators and Dictionary (key not found)

https://www.ageofascent.com/2018/01/26/stack-trace-for-excep...

Re:.NET 5.0 by hackerfromthefu on Tuesday November 17, 2020 @05:59AM (#25122282)
Awesome! Thank you. Wonderful to see these open source contributions to .NET.