任务数据流,完成状态下的数据块是否可以更改?

6
我想知道是否有可能更改数据块的完成状态?
例如,我使用var block = new BufferBlock<int>();创建了一个数据块,并使用block.Complete()标记它为完成。该块链接到其他数据块。我想知道是否可以通过将其完成状态更改回原始的未完成状态来使block再次运行。
如果不可能,如何在不必要解除所有块的链接、重新实例化所有块和重新链接所有块的情况下进行多次运行,包括完成每个块向下传递的流程?
有什么想法可以简化运行数据流周期的任务,包括完成链中的每个块,而无需重新创建整个框架吗?
谢谢

1
你为什么需要分开运行呢?另外,为什么不想重新创建数据流网络呢?我怀疑这不会影响性能(除非你每秒钟这样做很多次),而且也不应该让你的代码变得更加复杂。 - svick
分开运行是要求的一部分。重新创建整个网络将完全破坏通过选择 tpl 数据流获得的效率。主要的问题是取消链接和重新链接,而不是重新创建每个数据流块。如果改变完成状态是不可能的,那么我怎么能在不影响每个数据流块的完成状态的情况下发出完成信号呢?我不能只发送原子标志,因为链条下面的对象类型不相同(涉及到 transformblocks)。 - Matt
1个回答

4
不,您无法“取消完成”已完成的数据流块。我认为您应该为每个消息添加一个标志,指示它是否是运行中的最后一条消息。为了更方便地使用它,您可以创建一组帮助方法,例如:
public static TransformBlock<Tuple<TInput, bool>, Tuple<TOutput, bool>>
    CreateEnhancedTransformBlock<TInput, TOutput>(Func<TInput, TOutput> transform)
{
    return new TransformBlock<Tuple<TInput, bool>, Tuple<TOutput, bool>>(
        tuple => Tuple.Create(transform(tuple.Item1), tuple.Item2));
}

这种方式,您输入一个只处理TInputTOuputtransform委托,并且标志会随每个消息传输。


有趣的想法,您是否愿意评论一下通过这种方式执行时的计算开销?到目前为止,我只看到每个传入消息的接收器块的“完成标志”上增加了一个检查。还有其他我忽略的东西吗?相比布尔值,发送枚举是否更昂贵?这样我就可以传达除完成之外的其他状态了。 - Matt
1
@Freddy 可能会有一些微小的开销,因为有两个委托调用而不是一个,但这应该是非常可以忽略的。我认为用枚举替换 bool 也不会影响性能。 - svick
最终我还是采纳了你的第一个建议:浏览数据块的整洁完成特性并重新创建整个流水线,虽然解决这个问题的方法也不错。我为上游数据块包含的模块提供回调函数,在每个数据块完成时重新创建相同的数据块,并将其通过回调向下传递,两个数据块在下游重新链接。 - Matt
我还发现添加索引系统有助于识别数据的运行或批处理。这样做可以避免完全隔离运行。 - VoteCoffee

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