3

I have two tasks that can be run in parallel to increase performance:

var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();

await Task.WhenAll(task1, task2);

Now, I'm sure that these tasks are done. But per my understanding (and some real life headaches), if I call .Result on these tasks, I could cause a deadlock, even though they are complete?

From what I was reading,awaiting a completed task simply returns the result, so it seems like that is the way to go here. That makes my code look funky:

var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();

await Task.WhenAll(task1, task2);

var result1 = await task1;
var result2 = await task2;

Is this the correct way to solve this problem and get the results of both my tasks? If not, what's the problem? Is there a better way to unwrap the tasks without calling .Result on them?

6
  • 1
    FYI, async is not parallel Commented Jan 4, 2018 at 16:27
  • 1
    the Task.WhenAll is the parallel part I was referring to Commented Jan 4, 2018 at 16:28
  • 2
    @maccettura No, it's not, but the code shown here is, because it's starting multiple asynchronous operations without waiting for others to finish, resulting in them doing their work in parallel. Commented Jan 4, 2018 at 16:29
  • @Jonesopolis WhenAll doesn't make the work run in parallel. What makes it run in parallel is starting one task before the other has finished. Commented Jan 4, 2018 at 16:30
  • you're right. That is what I am getting at - allowing multiple tasks to start and waiting for them all to complete. Commented Jan 4, 2018 at 16:31

1 Answer 1

7

if I call .Result on these tasks, I could cause a deadlock, even though they are complete?

No, you can't. If the task is complete the Result will not block, it will immediately return, but more importantly you can't prevent the task that you're waiting on from finishing when it has already finished.

Is this the correct way to solve this problem and get the results of both my tasks?

It will certainly work. You are of course right that it looks silly, as you're redundantly awaiting the tasks twice (the second time won't actually take any time, as they're done, you're just typing out the code to wait for them twice). You can omit that redundant code, and simply await them the one time:

var task1 = _service.DoStuffAsync();
var task2 = _service.DoOtherStuffAsync();

var result1 = await task1;
var result2 = await task2;
Sign up to request clarification or add additional context in comments.

11 Comments

Ohhh that makes sense. Because both tasks are started, this would produce the same result in terms of efficiency.
Side note: before switching from WhenAll to separate awaits check discussion on "multiple await vs. WhenAll".
@AlexeiLevenkov Why link to a question that has an incorrect answer as the top and second highest answers if you want to bring it up?
Because I disagree with your statement that exception handling when all tasks failed is identical in both cases (multiple await vs. WhenAll). I'll be happy to see explanation of why both are identical, but unfortunately your answer is not currently covering that part of the topic. That's why I tried to word my comment as suggestion to read through discussion rather than blindly take one side of the discussion.
@AlexeiLevenkov In both situations if both tasks fail then the Task returned by the calling method will be the exception of the first method.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.