22

我正在寻找一种 TPL 数据流块解决方案,它可以容纳多个项目,它可以链接到多个目标块,但它能够将项目仅转发到通过过滤器/谓词的特定目标块。任何时候都不应将一个项目同时交付给多个目标块,始终只交付给与过滤器匹配的那个,否则该项目可以被丢弃。我不喜欢 BroadCastBlock,因为如果我理解正确,它不能保证交付(或者是吗?)并且过滤是在目标块端完成的,这意味着 BroadCastBlock 基本上将每个项目的副本发送到所有链接到目标块。如果我理解正确的话,它在任何时候都不会超过一件。我不想使用 Post/Async 但维护一个 LinkTo 链。

有没有办法绕过完整的自定义数据流块?还是我误解了 BroadCastBlock 的工作原理?不幸的是,没有太多的文档可以详细介绍并涵盖用例。任何想法都受到高度赞赏。

4

2 回答 2

35

如果我对您的理解正确,您想要的可以通过一个简单的 来完成BufferBlock,它将通过谓词链接到您的所有目标块。您还可以(无条件地)将其链接到一个NullTargetblock,以丢弃不匹配的项目。

就像是:

var forwarder = new BufferBlock<SomeType>();
forwarder.LinkTo(target1, item => matchesTarget1(item));
forwarder.LinkTo(target2, item => matchesTarget2(item));
forwarder.LinkTo(DataflowBlock.NullTarget<SomeType>());

这样,每个项目将被发送到第一个匹配的目标,如果有的话。

BroadcastBlock如果您想将每个项目发送到多个目标,或者如果您想在目标块不够快的情况下丢弃项目,则可能很有用。

使用BroadcastBlock,如果没有块接受它们,则项目可能会被丢弃(即使它们稍后可能能够接受)。但它不会随机丢弃项目,因此如果您的目标块没有BoundedCapacity设置,我认为您可以确定他们将获得所有他们不会拒绝的项目(例如,通过使用谓词 in LinkTo())。

于 2012-11-28T16:10:54.790 回答
11

我发现接受的答案不正确。NullTarget 应该与它的谓词联系起来,即消费者的否定。否则,您可能会丢弃您想要使用的消息。

var forwarder = new BufferBlock<SomeType>();
forwarder.LinkTo(target1, item => matchesTarget1(item));
forwarder.LinkTo(target2, item => matchesTarget2(item));
forwarder.LinkTo(DataflowBlock.NullTarget<SomeType>(), item => !matchesTarget1(item) && !matchesTarget2(item));
于 2015-06-19T19:55:05.890 回答