【问题标题】:How can I gather results from parallel async tasks in C#?如何从 C# 中的并行异步任务中收集结果?
【发布时间】:2022-02-03 13:04:28
【问题描述】:

我实际上面临异步任务的并行性问题。

我的目标是拥有一个异步Task,它连接到多个端点以检索相同类型的数据。提供了一个包含所有“连接字符串”的列表。数据检索应与所有连接并行发生,并且每个连接的检索数据应合并到一个容器中,一旦所有并行异步任务完成,该容器将被返回。

我的第一个想法是使用AsParallel.ForAll() - 传递配置和一个异步任务来用SendAsync 填充(数据流)BufferBlock。现在我陷入了这个问题,Parallel 查询似乎只将Action<T> 作为参数而不是Task<T>。如果发生异常,这将导致不良行为。

有人有更好的方法解决我的问题吗?

这是一个更好的可视化的 sn-p:

configurations.AsParallel().ForAll(async config => await FetchAllData(config,
    resultBufferBlock, cancellationToken));

经过一些 cmets:我基本上需要 .NET 6 中提供的 Parallel.ForEachAsync。我们将在几个月后迁移到 .NET 6。这是已经计划好的。虽然我很欣赏 .NET 5 的解决方案。实际上,看起来我会使用不好的方式将任务用作 Action 并稍后修复它......

【问题讨论】:

标签: c# asynchronous task-parallel-library .net-5 parallel.foreach


【解决方案1】:

我实际上遇到了异步任务的并行性问题。

您描述的问题是并发性(一次做不止一件事),而 AFAICT 不需要并行性(多线程)。

有人有更好的方法解决我的问题吗?

异步并发的方法是启动所有任务(通常使用带有异步 lambda 的 LINQ select),然后使用Task.WhenAll 加入它们。

var tasks = configurations.Select(async config => await FetchAllData(config, resultBufferBlock, cancellationToken));
await Task.WhenAll(tasks);

经过一些 cmets:我基本上需要 .NET 6 中可用的 Parallel.ForEachAsync。

我不同意。 Parallel.ForEachAsync 适用于当您有复杂的 CPU 绑定和 I/O 绑定代码混合并且需要同时执行并行性异步并发时。在这种情况下,不需要并行。

【讨论】:

    猜你喜欢
    • 2012-09-02
    • 1970-01-01
    • 2016-03-20
    • 2016-02-23
    • 1970-01-01
    • 2013-12-27
    • 2015-10-06
    相关资源
    最近更新 更多