任务与TPL数据流与异步/等待,何时使用?

时间:2012-11-27 06:25:40

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

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

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

我特别想知道何时使用任务,async / await和TPL数据流块以下内容:

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

  • 如何在(A),(B)和(C)中调用不直接参与数据生成和处理过程但执行可能需要几百毫秒/秒返回的配置工作的方法。我的预感是,这是async / await闪耀的地方?

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

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

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

1 个答案:

答案 0 :(得分:9)

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

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

Rx从一个非常不同的角度来看问题:它以“事件流”为中心,而不是TPL Dataflow的“演员网格”。最新版本的Rx非常async - 非常友好,因此您可以在Rx管道中的多个点使用async个委托。

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

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