使用async await实现动态并行是否不合适?

3

我正在编写一个将在ASP.NET Core (2.2)上运行的服务。在请求/响应的上下文中执行的工作对CPU资源的需求很高,没有依赖于I/O或其他基于网络的服务。由于所执行的工作性质,动态并行似乎是最佳方法。这不只是调用Parallel.ForEach,而是根据需要创建并运行任务。

这是背景。但我还没有搞清楚的是: 使用await async模式是否有优势或劣势?我可以创建任务并使用阻塞调用(如Task.WaitAll和Task.WaitAny)等待它们,也可以创建任务,并使用非阻塞调用(如Task.WhenAll和Task.WhenAny)进行await等待。

我在各种网站上看到了建议(尤其是在Stephen Cleary的书“Concurrency in C# Cookbook”,第3.4章中),要使用Task.Wait*方法来实现动态并行,但我不太明白为什么。在进行动态并行时,使用阻塞调用是否具有固有的优势?使用async/await方法会释放调用任务并等待被调用任务完成,不应该有自己的优势吗?

1个回答

1

动态并行性早于 asyncawait,通常在代码的某个部分中使用,希望阻塞,但您可以像等待 I/O 绑定任务一样等待 CPU 绑定任务。

根据我的经验,大多数情况下,动态并行性使用 AttachedToParent,这种方式为任务的所有子任务提供了隐式等待。不是实际的 Wait,因为线程没有被阻塞,而是更像 await 风格的 Wait。因此,在我的动态并行代码中,我不明确使用 await。但是,如果您不想阻止调用线程,则通常会有一个单独的顶级 await


好的。那听起来很合理。我采取的方法不会使用AttachedToParent。 - MMB
不小心在上面的评论中按下了“Enter”键....
好的。 那很有道理。 我采取的方法不会使用AttachedToParent。 相反,我创建了相当多的Tasks(通常比CPU数量更多),其中这些Tasks必须等待“预计算”Tasks完成后才能进行自己的计算。 这促使我采取了await / async方法。 给定这种设置,我从您那里听到的是以这种方式等待CPU绑定任务不应该成为问题。 对吗?
- MMB
另一个选择是伪管理任务。我并不是说要制作一个完整的任务调度程序,而是要利用 .net 提供的任务工具。 - Zakk Diaz
如果您没有使用AttachedToParent,您可以使用awaitContinueWith让一个任务依赖于另一个任务。我不确定在这种情况下哪种方法更好,但是如果混合使用它们,请特别注意包装的任务(例如Task<Task>)。 - Stephen Cleary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接