When to use OrderByCompletion (Jon Skeet) vs Parallel.ForEach with asynchronous delegates

Recently, John Skeet at NDC London talked about asynchronous / waiting for C # 5 and introduced the idea of ​​" sort by completion " async task list. Link http://msmvps.com/blogs/jon_skeet/archive/2012/01/16/eduasync-part-19-ordering-by-completion-ahead-of-time.aspx

I am a little confused or should say that I am not sure when this method will be more suitable for use.

I can not understand the difference between this and the example below

var bag = new ConcurrentBag<object>(); Parallel.ForEach(myCollection, async item => { // some pre stuff var response = await GetData(item); bag.Add(response); // some post stuff } 

or ForEachAsync , as Stephen Tuub explained - http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx

EDIT: Found a blog post from Stephen Toub explaining "Order completion" <=> "Processing tasks as they complete." Worth reading. After reading this, I could clearly understand the reasons why it works, as well as when to use this technique.

+5
c # async-await
source share
2 answers
  • Do not use Parallel.ForEach to execute async code. Parallel.ForEach does not understand async , so your lambda will be converted to async void , which will not work correctly ( Parallel.ForEach will return before everything is executed, exceptions will be handled incorrectly, maybe other issues).

  • Use something like ForEachAsync() , when you have a collection of objects (not Task s), you want to perform some kind of async action for each of them, and the actions must be executed in parallel.

  • Use OrderByCompletion() when you have a collection of Task s, you want to perform some action (asynchronous or not) for the result of each Task , the actions should not be executed in parallel, and you want to perform actions based on the completion order of the Task .

+15
source share
 Parallel.ForEach(myCollection, async item => 

This is almost certainly not what you want. The delegate is of type Action<T> , and therefore the anonymous method is an async void method. This means that it is starting, and you cannot check its status, except by checking any of its side effects. In particular, if something goes wrong, you cannot catch and handle the exception.

If all else fails, the results will be added to the bag as they are completed. Until nothing completes, bag will be empty.

In contrast, OrderByCompletion returns an IEnumerable<Task<T>> , which immediately contains tasks that are still not completed. You can await fifth element and continue when all five tasks are completed. This can be useful when, for example, you want to run a large number of tasks and periodically update the form to show progress.

The third option you gave, ForEachAsync , will behave like ForEach , except that it will do everything right, without the problems mentioned above.

+2
source share

All Articles