1

Background

I have an issue where I am hitting my method with very high load. The load is so high that it seems that it is causing resuming of await to have scheduling issues.

Basically, I was calling await httpClient.PostAsync(url, content);. But because I was hitting it so fast (multiple threads), I eventually got very long wait times on the client (the service was still responding very fast). From what I can see, this wait time was due to stress of getting 10s of thousands of resuming awaits scheduled on a thread.

Question

If I call httpClient.PostAsync(url, content).Result will that still result in a scheduled resuming of the remaining code, or will it really execute synchronously?

Vaccano
  • 78,325
  • 149
  • 468
  • 850
  • 3
    TL;DR; - you'll use roughly twice as many threads that way. What happens discussed many times and you likely can find better explanations than https://stackoverflow.com/questions/15021304/an-async-await-example-that-causes-a-deadlock (the only difference between core and regular asp.net is core one will not deadlock as it no longer uses synchronization context, but otherwise is the same). – Alexei Levenkov Aug 25 '20 at 21:09
  • 7
    Accessing .Result is a really really bad idea; that blocks a pool thread that wasn't expecting to be blocked - which can cause thread-pool starvation – Marc Gravell Aug 25 '20 at 21:10
  • @MarcGravell - If I use `await` I find that my `Parallel.ForEach` loop runs way past the `MaxDegreeOfParallelism` of 10 that I am trying to enforce. It seems that when the `await` is hit, it makes the parallel loop think that the thread is done, and it starts another. That is how I get to overwhelming the scheduler (and other resource issues). I want only 10 requests running at a time, but when I use await, I get way more than that. This has lead me to the awkward conclusion that I WANT it to block, so that I only ever get 10 running at a time. – Vaccano Aug 25 '20 at 21:21
  • 3
    @Vaccano yes, that's because Parallel.ForEach is using Action, which means that your `async` lambda is actually `async void`, which is *really really bad* (and will mean, among other things, that max-dop is not respected, but honestly: that's just the tip of the iceberg for reasons to never ever use `async void` outside of an event-handler). Ironically, the TPL (Parallel.ForEach) doesn't always play nicely with `async`/`await`, because it predates them. Or perhaps not ironic: parallelism and async are related but separate concepts – Marc Gravell Aug 25 '20 at 21:34
  • It sounds like what you want can be solved with something like this: https://devblogs.microsoft.com/pfxteam/implementing-a-simple-foreachasync-part-2/ – Jason Aug 25 '20 at 21:59

0 Answers0