0

I have a Web API controller that does the following:

    public async Task<Result> Post([FromBody] MyBody postBody)
    {
        // fire tasks
        var doSomethingTask = DoSomethingMethod();
        var doSomethingTask2 = DoSomethingMethod2();
        tasks.Add(doSomethingTask);
        tasks.Add(doSomethingTask2);

        Task.WaitAll(tasks.ToArray()); //line in question

        //do something async with results of these tasks
        await DoSomethingAsyncWithResults(doSomethingTask.Result,doSomethingTask2.Result);
   }

Now my question is in the above code should I actually be using

await Task.WhenAll(tasks.ToArray());

and what benefit - if any - would I see if I did that? Baring in mind this is a Web API controller so there is no UI to this application it's just getting called asynchronously from the frontend.

In my live environment there could be maybe 5 instances of this running, serving the front end. would locking up this method prevent it from responding to other requests?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
JKennedy
  • 18,150
  • 17
  • 114
  • 198
  • 1
    The big difference between them is that WaitAll return a Void (it blocks the current thread) instead, WhenAll, return a Task (we can decide to block or not the current thread). Reference Link: https://www.zoneofdevelopment.com/2022/07/27/ap-whenall-vs-waitall/#:~:text=The%20big%20difference%20between%20them,or%20not%20the%20current%20thread). Its totally selft explanatory solution. Do let me know if you need more information. – dLcreations Mar 09 '23 at 18:56

2 Answers2

0

what benefit - if any - would I see if I did that? Baring in mind this is a Web API controller so there is no UI to this application it's just getting called asynchronously from the frontend.

Your web server would use fewer threads to serve more requests. The benefit is scalability. A secondary benefit would be code consistency; the method is already async, so it's very weird to have the async method synchronously block when there is an awaitable alternative right there.

would locking up this method prevent it from responding to other requests?

No; ASP.NET is multithreaded by default. The difference is whether you want to use N threads or 0 threads during that multi-wait. See Synchronous vs Asynchronous Request Handling in my article Introduction to async/await on ASP.NET.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810
-2

.WaitAll() will block the calling thread and literally wait until everything is complete

.WhenAll() is like a way of wrapping a group of tasks in a singular Task object. As a result you can .Wait() or await them if you want. But there is more you can do, it is not bound by this waiting action if you deem it should do something else. It simply represents a Task that will move on to the next part to execute when all of its composed tasks complete. This version will not block the calling thread

Another key difference is exception handling. .WaitAll() will throw an AggregateException that contains all of the inner throws from faulted Tasks. .WhenAll() instead unwraps the AggregateException on its own and returns only the first exception

Update in response to updated code snippet: You absolutely need the return before moving on to execute the final line of the method here, so both .WaitAll() and await are valid here because in essence you are doing the same thing. If you need the ability to chain more tasks or logic onto it with later refactoring, then prefer to use the await version as it would be a little bit less re-writing

Task batch = Task.WhenAll(tasks.ToArray());
//chain on more things later
        
var batchResults = await batch;
Narish
  • 607
  • 4
  • 18