Live data from Hacker News

Asynchronous Programming in C#

github.com

151–160 of 186 posts

Re: Asynchronous Programming in C#

#151

So much content and the `ConfigureAwait` portion, which is the BIGGEST gotcha in the whole shebang in my opinion, is not filled out?! Especially for Xamarin, you need to understand and use ConfigureAwait to properly bounce between UI / background threads.

you can task.yield aswell.

Re: Asynchronous Programming in C#

#152

Earlier quoted context omitted.

Database operations should be async, you shouldn't consume them synchronously, as they do IO. Async/Await came out in 2012, almost a decade ago (and with great first party library support, I might add). Moralizing aside, sometimes you do want to call async APIs as synchronous code. I don't think there should be a synchronous version of the API implemented as well, you just need to do var myValue = DoSomethingAsync().…

Some things simply don't have an async API at the low level, e.g. DNS lookup: there is no asynchronous version of getaddrinfo(3). So if you look at the .NET sources, you'll see that Dns.GetHostEntryAsync pushes a task to a thread pool that calls getaddrinfo(3). In the end, you arrive at a "sync top-level APIs -- async library APIs -- sync low-level OS APIs" sandwich of dubious efficiency.

There is on windows. On Linux we queue the requests asynchronously to the same address (golang does similar things)

Re: Asynchronous Programming in C#

#153

Earlier quoted context omitted.

Some things simply don't have an async API at the low level, e.g. DNS lookup: there is no asynchronous version of getaddrinfo(3). So if you look at the .NET sources, you'll see that Dns.GetHostEntryAsync pushes a task to a thread pool that calls getaddrinfo(3). In the end, you arrive at a "sync top-level APIs -- async library APIs -- sync low-level OS APIs" sandwich of dubious efficiency.

When there's sync OS APIs what's the point of async over threads? I thought async APIs use async or polling version of syscalls and not blocking ones.

Because there are sometimes better things to do than block more threads. We can asynchronously queue dns requests to the same address (this is what we do in .NET 6)

Re: Asynchronous Programming in C#

#154
The most common issue I see with async programming is that the naive style seen in most samples/docs is strictly slower than standard imperative programming for one user. In other words, it's pure overhead with no benefit at all unless you're at a very large scale and approaching 100% capacity on your hosts.

Most documentation -- and most code I've seen in the wild -- reads like this:

    var foo = await GetFooAsync(...);
    var bar = await GetBarAsync(...);
    var baz = await GetBazAsync(...);
The timeline of that code is exactly same as the standard synchronous version, just with extra steps and pauses.

The following version is more verbose -- which makes it feel slower -- but can provide dramatic speed ups even for a single user by overlapping requests so that they run concurrently:

    var fooTask = GetFooAsync(...);
    var barTask = GetBarAsync(...);
    var bazTask = GetBazAsync(...);

    var foo = await fooTask;
    var bar = await barTask;
    var baz = await bazTask;
   
Unfortunately, I've literally never seen this design pattern in the field...

Re: Asynchronous Programming in C#

#156
post #96

Earlier quoted context omitted.

> Consider that the minimum grain of a Task.Delay is 1 millisecond. The minimum here is contingent on a few things. The API can accept a TimeSpan which can express durations as low as 100ns (10M ticks per second: https://docs.microsoft.com/dotnet/api/system.timespan.ticksp... ). The actual delay is subject to the timer frequency, which can be as high as 16ms and depends on the OS configuration (eg, see https://stacko…

> I'd recommend people take the simple approach of using async/await at the application layer and only change that approach if profiling demonstrates that it's becoming a performance bottleneck. Despite some of the things I presented in my original comment, I absolutely agree with this. There are only a few extreme cases where async/await simply can't get the job done. These edge cases are usually explicitly discover…

Honestly if you're in the situation where it comes down to individual CPU clock cycles I can't imagine C# (or similar Java, Go, etc.) being useful at that point. Too much going on that's not in the view of the developer.

Re: Asynchronous Programming in C#

#157

Why do we need the `async` keyword? What is the difference between a function which returns a Task , and an async function which returns a Task ?

`async` tells the compiler to generate a IAsyncStateMachine implementation https://ranjeet.dev/understanding-how-async-state-machine-wo...

Re: Asynchronous Programming in C#

#158

The most common issue I see with async programming is that the naive style seen in most samples/docs is strictly slower than standard imperative programming for one user . In other words, it's pure overhead with no benefit at all unless you're at a very large scale and approaching 100% capacity on your hosts. Most documentation -- and most code I've seen in the wild -- reads like this: var foo = await GetFooAsync(...…

Does C# not have an equivalent to JavaScript's Promise.all??

In JS this could be...

  const [
    fooTask,
    barTask,
    bazTask,
  ] = await Promise.all([
    GetFooAsync(...),
    GetBarAsync(...),
    GetBazAsync(...)
  ]);
... PS in your code above you assign GetBazAsync to bar and baz. :-)

Re: Asynchronous Programming in C#

#159

The most common issue I see with async programming is that the naive style seen in most samples/docs is strictly slower than standard imperative programming for one user . In other words, it's pure overhead with no benefit at all unless you're at a very large scale and approaching 100% capacity on your hosts. Most documentation -- and most code I've seen in the wild -- reads like this: var foo = await GetFooAsync(...…

Does C# not have an equivalent to JavaScript's Promise.all?? In JS this could be... const [ fooTask, barTask, bazTask, ] = await Promise.all([ GetFooAsync(...), GetBarAsync(...), GetBazAsync(...) ]); ... PS in your code above you assign GetBazAsync to bar and baz. :-)

Fixed!

I believe this kind of copy-paste "last line effect" one of the most common errors in programming: https://hownot2code.com/2016/08/15/the-last-line-effect-typo...

Task.WaitAll is the C# equivalent: https://docs.microsoft.com/en-us/dotnet/api/system.threading...

But it's not necessarily faster, there are corner cases where waiting for all tasks prevents some concurrent computations (e.g.: JSON parsing) from occurring.

Re: Asynchronous Programming in C#

#160

The most common issue I see with async programming is that the naive style seen in most samples/docs is strictly slower than standard imperative programming for one user . In other words, it's pure overhead with no benefit at all unless you're at a very large scale and approaching 100% capacity on your hosts. Most documentation -- and most code I've seen in the wild -- reads like this: var foo = await GetFooAsync(...…

Does C# not have an equivalent to JavaScript's Promise.all?? In JS this could be... const [ fooTask, barTask, bazTask, ] = await Promise.all([ GetFooAsync(...), GetBarAsync(...), GetBazAsync(...) ]); ... PS in your code above you assign GetBazAsync to bar and baz. :-)

There is Task.WhenAll which works similarly, but the problem is that it requires either all of the tasks to have the same return type, or else treat all the tasks in the array as untyped and extract the return values in a separate step.

i.e. you have to write

  var (fooTask, barTask, bazTask) = (GetFooAsync(), GetBarAsync(), GetBazAsync());
  await Task.WhenAll(fooTask, barTask, bazTask);
  var (foo, bar, baz) = (fooTask.Result, barTask.Result, bazTask.Result);
It's possible to write a custom awaiter extension method that allows awaiting tuples of tasks, so once that's in place you can just write

  var (foo, bar, baz) = await (GetFooAsync(), GetBarAsync(), GetBazAsync());
There are third-party packages that do this for you and it's reasonably easy to write yourself if you understand the inner workings of async/await, but it's not part of the standard library.
Post reply on HN