我正在学习数据流基础知识。 这是一个代码示例,对我来说看起来正确,但不起作用。 它不会返回结果整数值,而是冻结。 根据我的理解,这是因为完成不会在块之间传播。
public static int Process(int value)
{
var multiplyBlock = new TransformBlock<int, int>(item => item * 2);
var subtractBlock = new TransformBlock<int, int>(item => item - 2);
var options = new DataflowLinkOptions() { PropagateCompletion = true };
multiplyBlock.LinkTo(subtractBlock, options);
multiplyBlock.Post(value);
multiplyBlock.Complete();
subtractBlock.Completion.Wait(); // <--- code freezes here
return subtractBlock.Receive();
}
您能帮我了解缺少的内容吗?
当上游
subtractBlock.Complete()
完成时,会自动调用multiplyBlock.Completion
(因为PropagateCompletion = true
)。此时 subtractBlock.Completion
将不会立即完成。当以下两个条件同时成立时,它将完成:
subtractBlock
的输入缓冲区中的所有项目均已处理完毕。subtractBlock
的输出缓冲区中的所有项目已被下游的块接受。换句话说,
TransformBlock<TInput, TOutput>
的输入和输出缓冲区都必须为空,否则该块将永远不会完成。在您的情况下,块的输出缓冲区未清空,因为该块未链接到任何内容。您可以通过将其链接到 NullTarget
或将其替换为 ActionBlock<TInput>
来解决此问题。
顺便说一句,请注意,目前 TPL 数据流库存在一个错误,在非常特定和罕见的情况下,可能会导致管道永远无法完成。您可以在here找到此错误的演示。这个错误一直存在,不太可能很快得到解决。