6

In the following code task1 and task2 are independent of each other and can run in parallel. What is the difference between following two implementations?

var task1 = GetList1Async();
var task2 = GetList2Async();

await Task.WhenAll(task1, task2);

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

and

var task1 = GetList1Async();
var task2 = GetList2Async();

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

Why should I choose one over the other?

Edit: I would like to add that return type of GetList1Async() and GetList2Async() methods are different.


  • I4v, in the first case, var result = await task1; would be the exact same of var result = task1.Result. I do think that .Result is more readable though. - dcastro
  • @I4V Nope. In both snippets the tasks are run in parallel, not sequentially. - Servy
  • @dcastro, they are not the same. In the case of an exception, using .Result results in different exception being generated (an AggregateException) than when using await (the first exception), so when using async/await you should prefer using await over .Result to keep exception behavior consistent. - Matt Smith
  • But if there's an exception it'll be thrown when awaiting all, and you'll never get to the two lines below that. Assuming you do get to the two lines below that, you can .Result without worrying about exceptions or deadlocking because it's guaranteed the tasks have already completed. Refer to stackoverflow.com/a/24657079/1676558. - user1676558

2 답변


10

Your first example will wait for both tasks to complete and then retrieve the results of both.

Your second example will wait for the tasks to complete one at a time.

You should use whichever one is clearer for your code. If both tasks have the same result type, you can retrieve the results from WhenAll as such:

var results = await Task.WhenAll(task1, task2);


  • Apart from intent clarity, if the conditions are right (2 or more CPU cores are idle) is the chances of solution 1 being parallel more than solution 2 ? - Snakebyte
  • @Snakebyte No, there is not. They'll both perform identically, with only a very tiny bit of extra overhead in the first case as it's performing a WhenAll needlessly. - Servy
  • @Servy: What do you mean exactly? As I understand and Stephan states is that in example1 task1 and task2 are executed in paralel. In example 2 they are not executed paralel, task 1 is executed and the main thread returns when the result is completed and starts executing task 2. - Maarten Kieft
  • @BlackHawkDesign: No, in both cases they execute concurrently. The question is whether the parent method waits for them concurrently or one at a time. - Stephen Cleary
  • @Stephen Cleary: I see what you mean, you/servery are right. I interpreted the 2nd piece of code as: var task1 = await GetList1Async(); var task2 = await GetList2Async(); In that case they would be executed after each other. But you are right, in this case they are both executed in paralel. - Maarten Kieft

1

The first construct is more readable. You clearly state that you intend to wait for all tasks to complete, before obtaining the results. I find it reasonable enough to use that instead the second.

Also less writing, if you add a 3rd or 4th task... I.e. :

await Task.WhenAll(task1, task2, task3, task4);

compared to:

var result1 = await task1; 
var result2 = await task2; 
var result3 = await task3; 
var result4 = await task4; 


  • But in the first sample he goes and awaits all of the component tasks anyway. It's only a win if you avoid doing that and use the return value of WhenAll instead. - Servy
  • What a 'win' is seems subjective in this case. Task.WhenAll is not completely the same as awaiting the tasks individually (as Servy knows). Take a look at stackoverflow.com/q/18310996/1676558 if you want to start learning more about this issue. - user1676558

Linked


Related

Latest