1

我想询问如何使用 TPL Dataflow 最好地设计最佳架构。我还没有编写代码,所以没有可以发布的示例代码。我也不是在寻找代码(除非自愿),但非常感谢设计方面的帮助:

要求如下:

我有 3 个以特定方式相互依赖的核心数据块。Datablock1 是生产 Foo1 类型对象的生产者。Datablock2 应该订阅 Foo1 对象(来自 Datablock1),并且可能(不是在每个 Foo1 上,受特定函数约束)生成 Foo2 对象,并将其存储在输出队列中以供其他数据块使用。Datablock3 还使用 Foo1 对象(来自 Datablock1)并可能生成 Foo3 对象,Datablock2 使用这些对象并转换为 Foo2 对象。

总而言之,以下是数据块以及它们各自产生和消耗的内容:

  • Datablock1:生产(Foo1),消费(无)
  • Datablock2:生产(Foo2),消费(Foo1,Foo3)
  • Datablock3:生产(Foo3),消费(Foo1)

另一个要求是在 Datablock2 和 Datablock3 中几乎同时处理相同的 Foo1。如果 Foo1 对象首先由 Datablock2 使用,然后一旦 Datablock2 完成其工作,同样的 Foo1 对象将被发布到 Datablock3 以供其工作。Datablock2 中的 Foo2 对象可以来自对 Foo1 对象或 Foo3 对象的操作。

我希望这是有道理的,如果仍然不清楚,我很乐意解释更多。

我的第一个想法是为 3 个数据块中的每一个创建 TPL 数据流块,并让它们处理不同对象类型的传入流。另一个想法是拆分数据块,让每个数据块只处理一种对象类型的流。您有什么建议,或者是否有更好的解决方案可能有效?

Svick 已经在 Datablock1 上提供了帮助,它已经投入使用,我只是纠结于如何将我当前的环境(如上所述)转换为 TPL Dataflow。

任何想法或指针都非常感谢。

4

1 回答 1

4

让我们把这个问题分成三个并独立解决。

第一个是如何有条件地生产一个项目。我认为最好的选择是使用TransformManyBlock并让您的函数返回一个包含一个或零个项目的集合。

另一种选择是有条件地链接两个块,以便nulls 被忽略并null在您不想产生任何东西时返回。但是如果你这样做,你还必须将源链接到 a NullTarget,这样nulls 就不会留在它的输出缓冲区中。

第二个问题是如何将 Foo1s 发送到块#2 和块#3。我可以在这里看到两种方式:

  1. 使用BroadcastBlock链接到两个目标块(#2 和#3)。小心这一点,因为BroadcastBlock没有输出队列,所以如果目标块推迟了一个项目,这意味着它不会处理它。因此,在这种情况下,您不应该设置BoundedCapacity块 #2 和 #3。如果您不这样做,它们将永远不会推迟,所有消息都将由两个块处理。
  2. 在块 #2 处理 Foo1 之后,手动Post()(或更好地SendAsync())将其用于块 #3。

我不确定“大约在同一时间”到底是什么意思,但总的来说,TPL Dataflow 不对独立块的处理顺序做出任何保证。您可以使用customTaskScheduler更改不同块的优先级,但我不确定这在这里是否有用。

最后一个也是最复杂的问题是如何在单个块中处理不同类型的项目。有几种方法可以做到这一点,但我不确定哪种方法最适合您:

  1. 不要在单个块中处理它们。有一个TransformBlock<Foo1, Foo2>和一个TransformBlock<Foo3, Foo2>。然后,您可以将它们都链接到一个BufferBlock<Foo2>.
  2. 正如您所建议的,使用BatchedJoinBlock<Foo1, Foo3>, with batchSizeof 1。这意味着结果Tuple<IList<Foo1>, IList<Foo3>>将始终包含 oneFoo1或 one Foo3
  3. BatchedJoinBlock通过将 链接到TransformBlock产生更合适类型的 a 来增强先前的解决方案。这可能是Tuple<Foo1, Foo3>(其中一项将始终为null)或类似 F# 的东西Choice<Foo1, Foo3>,它确保仅设置两者中的一项。
  4. 从头开始创建一个新的块类型,这正是您想要的。它应该ISourceBlock<Foo2>并且也有两个属性:Target1类型ITarget<Foo1>Target2类型ITarget<Foo3>,就像内置的连接块一样。

使用选项 #1 和 #3,您还可以将块封装到单个自定义块中,从外部看起来就像 #4 中的块,以便更容易重用。

于 2012-06-29T13:50:32.920 回答