Live data from Hacker News

Asynchronous Programming in C#

github.com

161–170 of 186 posts

Re: Asynchronous Programming in C#

#161

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 foo = await GetFooAsync(...);

var bar = await GetBarAsync(...);

var baz = await GetBazAsync(...);

Unfortunately this is the kind of example that is being used in the MS docs and elsewhere to explain async. I spent a long time figuring out what the difference was when they ran the exact same way as the synchronous version.

Re: Asynchronous Programming in C#

#162
post #96

Earlier quoted context omitted.

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

Some of the highest throughput systems on earth are written in either Java or C#.

Check out the LMAX disruptor sometime. Throughput rates measured in hundreds of millions of serialized events per second are feasible in these languages if you are clever with how you do things.

Re: Asynchronous Programming in C#

#163
post #104

Is there a rule as to which methods are best made async and which not? Or, once you start using async would it be best to make ALL methods async? Many methods could be either sync or async. But if you make a method that doesn't strictly need to be async async you give yourself the option of later making it actually return its result after a delay, say reading its answer from the web or asynchronously from disk. Where…

I recently had to make a change that converted a few functions to be async. It was certainly annoying to propagate that back in all the signatures, but the biggest issues came with having code that was designed under the assumption that the code would be synchronous. It was difficult to rework the code in ways that would avoid issues with things like the fact that if I use a member variable, call one of these functio…

> use a member variable, call one of these functions, and then use use that variable again, there's no longer a guarantee that the variable still has the same value.

Could you expound upon this? Not sure I understand the context, but would like to. Are you assigning a value to a member variable by awaiting the return of an async method, not clear would cause you to lose the value.

Re: Asynchronous Programming in C#

#164

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(...…

This is indeed bad for usual cases but in general you can't say it's always bad. For example, if you need to call 1 million asnyc methods, you will benefit from batching them and running a small number at a time.

Re: Asynchronous Programming in C#

#165
post #102

Am I completely crazy in thinking that we use the terms sync and async incorrectly in software? Synchronous: Simultaneous, at the same time. Asynchronous: Not Synchronous So the basic category would be something like serial vs not serial where the "not serial" part consists of two approaches, synchronous, threads or forks for instance, and asynchronous, selectors and callbacks. Right?...RIGHT?!?! Why do we refer to b…

There is no spoon

Re: Asynchronous Programming in C#

#166

Earlier quoted context omitted.

.NET Core and later has ValueTask for that usecase.

but shouldnt it be that ValueTask is used everywhere by default and class "exists for some usecase"?

If you know that an operation will not complete sychronously (e.g. because it requires a network transaction) then normal Task might actually be more efficient, because the heap allocation would be required anyway and you safe the additional branches.

Re: Asynchronous Programming in C#

#167

What's the right way to do throttled async in modern C#? For some context, we have a process that needs to make an API call for each row in a file - maybe hundreds or thousands. What's the best way beyond Wait()'ing for each one to get decent performance without DOS'ing the server?

I personally used a semaphore for that. You create a semaphore with an initial count of MAX_REQS_PER_SECOND, create WORKER_COUNT of looping "worker" tasks that each call WaitAsync() on that semaphore before doing request (and don't call Release() after request is done), plus a separate task that does either Sleep(100); Release(MAX_REQS_PER_SECOND / 10); or Sleep(1000 * WORKER_COUNT / MAX_REQS_PER_SECOND); Release(WOR…

[deleted]

Re: Asynchronous Programming in C#

#168
post #84

I used C#'s async/await on a project in 2017, and I took to it. I appreciated being able to follow the "relevant" parts of a method, without having to jump around to different callbacks. That being said, I think I was the only one on the project that understood it _well_. Over the course of two years, I learned lots of the same gotchas. Avoid "async void" was one of the catchy mnemonics I learned the hard way, becaus…

Given that you understand it well -- do you know why the compiler accepts async void in the first place?

Re: Asynchronous Programming in C#

#169
post #83

What's the right way to do throttled async in modern C#? For some context, we have a process that needs to make an API call for each row in a file - maybe hundreds or thousands. What's the best way beyond Wait()'ing for each one to get decent performance without DOS'ing the server?

Use System.Threading.Channels. BoundedChannelFullMode.DropNewest, DropOldest, DropWrite, Wait specifies the behavior to use when writing to a bounded channel that is already full

Thank you! I didn't know that existed. I gotta test the performance of that compared to something like a list or array with an explicit lock, which is otherwise my go to solution precisely for performance reasons.

Re: Asynchronous Programming in C#

#170

async/await makes things complicated - this is a great illustration of some issues with it. Fibers/green threads/goroutines seem to be generally easier and not viral. C#/dotnet choosing this the async model always bothered me. Otherwise, the platform is solid. It's interesting, therefore, to try to understand why dotnet went with the async/await model. A language maintainer C# talks about the issue here and reference…

I think for C# one of the strong async use-cases was the same one as for Javascript having async/await: UI programming. UI environments are mostly single-threaded, and if you want to modify UI elements you have to perform that operation on the UI thread. Doing e.g. a HTTP download in a background thread and directly manipulating a progress bar from there wasn't possible. With async/await that can multiplex all those async tasks onto the UI thread this now gets feasible. With the move to more declarative UI patterns this argument might now get more mood, but I don't have enough recent experience to tell.

On the server end, I strongly agree with you that for 95% of applications a threaded environment - and even using plain OS threads - would likely be easier and fast enough. But I guess everyone also wants to support the remaining 5% of applications, like "build a 100k clients proxy server".

Btw: Fibers can also be viral. E.g. if they are multiplexed on a single OS thread (non work-stealing scheduler) you still can't block in them, and need fiber-aware methods of everything. If you use a work-stealing scheduler then methods which use thread-local storage might be subject to undefined behavior, because the currrent thread might change inside the execution of the function at an invisible yield point.

Post reply on HN