Mat*_*olf 5 c# concurrency message-passing task-parallel-library tpl-dataflow
鉴于以下情况:
BufferBlock<int> sourceBlock = new BufferBlock<int>();
TransformBlock<int, int> targetBlock = new TransformBlock<int, int>(element =>
{
return element * 2;
});
sourceBlock.LinkTo(targetBlock, new DataflowLinkOptions { PropagateCompletion = true });
//feed some elements into the buffer block
for(int i = 1; i <= 1000000; i++)
{
sourceBlock.SendAsync(i);
}
sourceBlock.Complete();
targetBlock.Completion.ContinueWith(_ =>
{
//notify completion of the target block
});
Run Code Online (Sandbox Code Playgroud)
在targetBlock似乎永远不会完成,我想原因是,在所有的项目TransformBlock targetBlock在输出队列中等待,因为我还没有链接的targetBlock其他任何数据流块。但是,我真正想要实现的是当(A)targetBlock通知完成和(B)输入队列为空时的通知。我不想关心项目是否仍然位于TransformBlock. 我该怎么办?是让我想查询的完成状态什么的唯一方式sourceBlock,并确保了InputCount的targetBlock是零?我不确定这是否非常稳定(sourceBlock如果中的最后一项sourceBlock已传递给targetBlock?)。有没有更优雅、更有效的方法来达到同样的目标?
编辑:我刚刚注意到,即使是“肮脏”的方式来检查零的sourceBlockANDInputCount的完成情况targetBlock也不是很容易实现。那个街区会坐在哪里?它不能在其中,targetBlock因为一旦满足上述两个条件,显然不再处理任何消息targetBlock。还要检查 的完成状态会sourceBlock带来很多低效率。
我相信你不能直接这样做。您可以private使用反射从某些字段获取此信息,但我不建议这样做。
但您可以通过创建自定义块来做到这一点。如果情况Complete()很简单:只需创建一个块,将每个方法转发到原始块。除了 之外Complete(),它还会记录它。
在确定所有项目的处理何时完成的情况下,您可以将您的块链接到中间BufferBlock. 这样,输出队列将很快被清空,因此检查Completed内部块将为您提供相当准确的处理何时完成的测量。这会影响您的测量,但希望影响不会很大。
另一种选择是在块委托的末尾添加一些日志记录。这样,您就可以看到最后一项的处理何时完成。