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

Must we wait for all async calls when using Parallel.Foreach?

假设我们有一个过滤器列表,使用Parallel.ForEach进行异步调用然后使用它们是否可以?我们必须等待所有呼叫结束吗?如果我们有 3 个异步调用和一个 fails/times 输出怎么办?

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
   }
}

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

serviceClient.GetAllAsync(filter)

正在不同的 thread/task 中做某事或对某些 url 提出请求,我认为没有必要使用 Paralle.ForEach。

我要做的是创建一个任务列表并使用 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.
        }

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 将帮助您处理异常。