【问题标题】:Tasks vs. TPL Dataflow vs. Async/Await, which to use when?Tasks vs. TPL Dataflow vs. Async/Await,什么时候使用?
【发布时间】:2012-11-27 06:25:39
【问题描述】:

我已经阅读了 Microsoft 团队的一些成员或其他作者提供的大量技术文档,这些文档详细介绍了新的 TPL 数据流库、异步/等待并发框架和 TPL 的功能。但是,我还没有真正遇到任何明确描述何时使用的内容。我知道每个都有自己的位置和适用性,但我特别想知道以下情况:

我有一个完全在进程内运行的数据流模型。顶部是一个数据生成组件 (A),它生成数据并通过数据流块链接或通过引发事件将其传递给处理组件 (B)。 (B) 中的某些部分必须同步运行,而 (A) 大量受益于并行性,因为大多数进程都受 I/O 或 CPU 限制(从磁盘读取二进制数据,然后对其进行反序列化和排序)。最后,处理组件 (B) 将转换后的结果传递给 (C) 以供进一步使用。

我特别想知道何时在以下方面使用任务、异步/等待和 TPL 数据流块:

  • 启动数据生成组件 (A)。我显然不想锁定 gui/仪表板,因此这个过程必须在不同的线程/任务上运行。

  • 如何调用 (A)、(B) 和 (C) 中不直接参与数据生成和处理过程但执行可能需要数百毫秒/秒才能返回的配置工作的方法.我的直觉是,这就是 async/await 的亮点?

  • 我最纠结的是如何最好地设计从一个组件传递到下一个组件的消息。 TPL 数据流看起来很有趣,但有时对我的目的来说太慢了。 (注意最后关于性能问题)。如果不使用 TPL Dataflow,我如何通过进程间任务/并发数据传递来实现响应性和并发性?例如,如果我在任务中引发事件,订阅的事件处理程序会在同一个任务中运行,而不是传递给另一个任务,对吗?综上所述,组件(A)在将数据传递给组件(B)而组件(B)检索数据并专注于处理数据后如何开展业务?这里最好使用哪种并发模型? 我在这里实现了数据流块,但这真的是最好的方法吗?

  • 我想以上几点总结表明我在如何使用标准实践设计和实现 API 类型组件方面遇到困难?方法是否应该设计为异步的,数据输入作为数据流块,数据输出作为数据流块或事件?一般来说,最好的方法是什么?我之所以问,是因为上面提到的大多数组件都应该独立工作,因此它们基本上可以在内部被换出或独立更改,而无需重新编写访问器和输出。

性能说明:我提到 TPL 数据流块有时很慢。我处理高吞吐量、低延迟类型的应用程序和目标磁盘 I/O 限制,因此 tpl 数据流块的执行速度通常比同步处理单元慢得多。问题是我不知道如何将流程嵌入到它自己的任务或并发模型中以实现与 tpl 数据流块已经处理的类似的东西,但没有 tpl df 带来的开销。

【问题讨论】:

  • “一般来说最好的方法是什么?”我认为没有。编程通常是关于考虑替代方案,并且没有一个在所有情况下都是最好的。这也是为什么当你关心性能时,你应该使用分析,没有“X总是比Y好”。
  • @svick,非常尊重您的专业知识和意见,但这就是为什么我指定了一个用例,并考虑在哪种方法最适合时提出具体的、有针对性的问题。您介意分享您将如何处理 4 个要点中的每一个的知识吗?非常感谢
  • 随时在Meta Stack Overflow 上提出关闭。
  • @Freddy 不,因为你在错误的地方不同意。这是您被指向Meta Stack Overflow 的第一次(迄今为止的两次)。评论是为了澄清问题。它们不适用于元评论(问题应该是开放式、封闭式等)。

标签: task-parallel-library async-await tpl-dataflow


【解决方案1】:

听起来你有一个“推送”系统。普通的async 代码只处理“拉”场景。

您可以在 TPL 数据流和Rx 之间进行选择。我认为 TPL 数据流更容易学习,但既然你已经尝试过了,它不适用于你的情况,我会尝试 Rx。

Rx 从一个非常不同的角度来解决问题:它以“事件流”而不是 TPL 数据流的“参与者网格”为中心。最新版本的 Rx 对 async 非常友好,因此您可以在 Rx 管道中的多个点使用 async 代表。

关于您的 API 设计,TPL Dataflow 和 Rx 都提供了您应该实现的接口:IReceivableSourceBlock/ITargetBlock 用于 TPL Dataflow,IObservable/IObserver 用于 Rx。您可以将实现连接到内部网格(TPL 数据流)或查询(Rx)的端点。这样,您的组件就只是一个“块”或“可观察/观察者/主题”,可以在其他“网格”或“查询”中组合。

最后,对于您的async 构造系统,您只需要使用工厂模式即可。您的实现可以调用Task.Run 对线程池线程进行配置。

【讨论】:

  • 你什么时候会选择使用“推送”系统,而不是在异步方法返回结果后编写处理数据的方法?在阅读了您推荐使用数据流的几篇文章后,我打开了一个问题here,但我仍然不确定我是否完全理解在等待异步任务后仅添加流程方法的好处,请您详细说明或参考我在那个问题中写的示例?
  • 大多数系统本质上是“推”或“拉”,如果您想以其他方式使用它们,则需要翻译(后台进程/缓冲区)。例如,从数据库中检索记录是一个“拉”系统;用户输入是一个“推送”系统。对于手头的情况,我更喜欢使用更自然的方法;例如,使用 async 进行数据库查询并使用 events/Rx 来响应 UI 输入。
猜你喜欢
  • 2014-07-19
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
  • 2018-10-09
  • 2012-11-02
  • 1970-01-01
  • 2015-10-27
相关资源
最近更新 更多