跳过数据流TransformBlock中的项目

24

TPL Dataflow 提供了一个用于转换输入的TransformBlock,例如:

var tb = new TransformBlock<int, int>(i => i * 2);

是否可能不输出输入的某些部分,例如如果输入未通过某些验证测试?

var tb = new TransformBlock<InputType, OutputType>(i =>
{
    if (!ValidateInput(i))
    {
        // Do something to not output anything for this input
    }
    // Normal output
}

如果不可能实现,那么达到这个目标的最佳模式是什么?
类似以下内容?

BufferBlock<OutputType> output = new BufferBlock<OutputType>();

var ab = new ActionBlock<InputType>(i =>
{
    if (ValidateInput(i)) 
    {
        output.Post(MyTransform(i));
    }
}
3个回答

26

有几种方法可以实现此目的:

  1. 像Jon建议的那样使用TransformManyBlock,并返回包含1或0项的集合。
  2. 使用带有代表“无值”的特殊值(例如 null)的TransformBlock ,然后使用过滤器的LinkTo()来删除它们。你还需要将TransformBlock链接到没有过滤器的空块(DataflowBlock.NullTarget<T>()),以排出特殊值。
  3. 我认为这算是一种不太正规的方法,但你也可以使用TransformBlock的基于Task的构造函数:在想要返回值时使用Task.FromResult(),不想要返回值时使用null。例如:

    new TransformBlock<int, int>(i => i % 2 == 0 ? Task.FromResult(i * 2) : null)
    

13

我自己并没有使用过 DataFlow,但是我认为你可以使用 TransformManyBlock,并且只需使每个步骤返回一个空集合或单个项。

var tmb = new TransformManyBlock<InputType, OutputType>(i =>
{
    if (!ValidateInput(i))
    {
        return Enumerable.Empty<OutputType>();
    }
    ...
    // Or return new[] { outputValue };
    return Enumerable.Repeat(outputValue, 1);
});

你甚至可以将它泛化为一个 FilterBlock<T>,它只有一个过滤谓词,并通过传递适当的匹配项(就像LINQ中的Where一样)进行操作。最初可以使用上面的TransformManyBlock来实现它,但稍后可以使其更有效率。


9

分享一些经验:如果你想处理数据,可以使用BufferBlock代替ActionBlock,并使用LinkTo扩展方法和条件谓词,这样只有满足条件的值才会传递到TransformBlock,不符合条件的值将被忽略。要丢弃无效的值,可以简单地使用NullTarget块,该块只是忽略它接收到的数据。因此,最终代码可能如下所示:

var input = new BufferBlock<int>();
var tb = new TransformBlock<int, int>(i => i * 2);
var output = new BufferBlock<int>();

// valid integers will pass to the transform
input.LinkTo(tb, i => ValidateInput(i));

// not valid will be discarded
input.LinkTo(DataflowBlock.NullTarget<int>());

// transformed data will come to the output
tb.LinkTo(output);

同时,链接可以通过一些DataflowLinkOptions其他的LinkTo重载进行调整。


这本质上是svick答案中的选项(2)。 - Gordon Bean
@GordonBean 增加了块之间的直接链接。 - VMAtm

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