如何从 C# 中的并行异步任务收集结果?

How can I gather results from parallel async tasks in C#?

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

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

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

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

为了更好地可视化,这里有一个片段:

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

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

I'm actually facing a problem with parallelism on asynchronous tasks.

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

Does anyone have a better approach to my problem?

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

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

After some comments: I basically need Parallel.ForEachAsync which is available in .NET 6.

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