【问题标题】:Task Dataflow, can a data block be changed from completion state?任务数据流,可以从完成状态更改数据块吗?
【发布时间】:2013-04-12 09:38:39
【问题描述】:

我想知道是否可以改变数据块的完成状态?

例如,我用block.Complete() 标记了一个完整的var block = new BufferBlock<int>(); 数据块。该块链接到其他数据块。我想知道是否可以通过将 block 的完成状态更改回其原始 !complete 状态来再次运行。

如果这是不可能的,我如何执行多次运行,包括完成,而不必 a) 取消链接所有块,b) 重新实例化所有块,以及 c) 再次重新链接所有块?

有什么想法可以简化运行数据流周期的任务,包括完成链下的每个块,而无需重新创建整个框架?

谢谢

【问题讨论】:

  • 为什么还需要单独运行?另外,您为什么不想重新创建数据流网络?我怀疑它会影响性能(除非您每秒执行多次)并且它也不应该使您的代码变得更加复杂。
  • 单独运行是要求的一部分。重新创建整个网络将完全破坏通过选择 tpl 数据流获得的效率。主要令人头疼的是取消链接和重新链接,而不是重新创建每个数据流块。如果改变完成状态是不可能的,我怎么能在不影响每个数据流块的完成状态的情况下发出完成信号?我不能只发送一个原子标志,因为链中的对象类型并不相同(涉及到变换块)。

标签: c# task-parallel-library tpl-dataflow


【解决方案1】:

不,您不能“取消完成”已完成的数据流块。我认为您应该做的是为每条消息添加一个标志,说明它是否是运行中的最后一条消息。为了使其更易于使用,您可以创建一组辅助方法,例如:

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 委托,并且该标志与每条消息一起传输。

【讨论】:

  • 有趣的想法,您是否愿意通过这条路线评论执行期间的计算开销?到目前为止,我只看到对每个传入消息的接收器块的“完成标志”进行额外检查。还有什么我省略了吗?发送枚举而不是布尔会更昂贵吗?通过这种方式,我可以传达其他状态,而不仅仅是完成。
  • @Freddy 可能会有一些微小的开销,因为有两个委托调用而不是一个,但这应该可以忽略不计。而且我认为用枚举替换 bool 也不应该影响性能。
  • 绝对是解决这个问题的好主意,但最后我还是采纳了你的第一个建议:我仔细研究了数据块的整洁完成功能并重新创建了整个管道。我为包含模块的上游数据块提供回调,并在每个数据块完成后重新创建相同的数据块并通过下游的回调将其传递给重新链接两个块的下游。
  • 我还发现添加索引系统有助于识别运行或批量数据。这使得运行不需要完全隔离。
猜你喜欢
  • 1970-01-01
  • 2022-12-04
  • 2021-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多