使用Parallel.Foreach时,我们必须等待所有异步调用吗?

时间:2018-12-24 12:25:54

标签: c# parallel-processing async-await parallel.foreach

假设我们有一个过滤器列表,可以使用Parallel.ForEach进行异步调用然后使用它们吗?我们必须等待所有通话结束吗?如果我们有3个异步呼叫而一个失败/超时怎么办?

var results = new ConcurrentBag<Service>();

Parallel.ForEach(filters, async filter =>
{
   var result = await serviceClient.GetAllAsync(filter).ConfigureAwait(false);

   results.AddRange(result);
});

MyMapper.Map(results);

其中MyMapper具有方法:

Map(IEnumerable<Service> services) {
   foreach(Service service in services) {
      //do stuff
   }
}

2 个答案:

答案 0 :(得分:2)

Parallel库被认为可以并行处理数百万个项目。使用Parallel.ForEach不会有任何改善。您可以改用Task.WhenAll

var tasks = new List<Task>();

foreach(var filter in filters)
{
   tasks.Add(serviceClient.GetAllAsync(filter));
}

results.AddRange(await Task.WhenAll(tasks).ConfigureAwait(false));

您可以执行一些LinQ。我没有,这个主意更清楚了。 使用此代码,您可以具有一定程度的并行性,await将帮助您解决异常情况。

答案 1 :(得分:-3)

我会做些不同的事情。假设

serviceClient.GetAllAsync(filter)

在不同的线程/任务中执行某项操作,或者对某个URL进行了请求,我看不到需要Paralle.ForEach用法。

我要做的是创建一个Task列表,并使用Task.WaitAll方法调用它们。这样,您就可以处理错误任务的所有异常。

此代码段类似于以下内容:

  var queryService = filters.Select(x => sClient.GetAllAsync()).ToArray();

        try
        {
            // Wait for all the tasks to finish.
            Task.WaitAll(queryService);
        }
        catch (AggregateException e)
        {
            //At least one of the Task instances was canceled.
            //If a task was canceled, the AggregateException contains an OperationCanceledException in its InnerExceptions collection.
        }