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

别来无恙 提交于 2019-12-31 22:41:52

问题


Recently Jon Skeet at NDC London spoke about C# 5 async/await and presented the idea of "ordering by completion" a list of async tasks. A link http://msmvps.com/blogs/jon_skeet/archive/2012/01/16/eduasync-part-19-ordering-by-completion-ahead-of-time.aspx

I am a bit confused or should I say I am not sure when will this technique be more appropriate to use.

I cannot understand the difference between this and the below example

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 explained by Stephen Toub - http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx

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


回答1:


  • Don't use Parallel.ForEach to execute async code. Parallel.ForEach doesn't understand async, so your lambda will be turned into async void, which won't work correctly (Parallel.ForEach will return before all work is done; exceptions won't be handled properly; possibly other issues).

  • Use something like ForEachAsync() when you have a collection of objects (not Tasks), you want to perform some async action for each of them and the actions should execute in parallel.

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




回答2:


Parallel.ForEach(myCollection, async item =>

This is almost certainly not what you want. The delegate has type Action<T>, and so the anonymous method is an async void method. That means it gets launched, and you have no way of checking its status other than by checking for any of its side effects. In particular, if anything goes wrong, you cannot catch and handle the exception.

Assuming nothing goes wrong, though, results will be added to bag as they complete. Until anything completes, bag will be empty.

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

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



来源:https://stackoverflow.com/questions/20478114/when-to-use-orderbycompletion-jon-skeet-vs-parallel-foreach-with-async-delegat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!