[英]TPL Dataflow C# wait for all linked blocks to complete
I'm using TPL Dataflow to build a pipeline.我正在使用 TPL Dataflow 来构建管道。 This pipeline should logically do the following:此管道应在逻辑上执行以下操作:
pollingBlock
.从处理多个数据项开始——假设它是pollingBlock
。monitoringBlock
.如果满足某些条件,则将其中一项(已满足条件)传递给某个块以进行进一步监控,假设它是monitoringBlock
。 Each monitoringBlock
can hold only 1 item, but there are multiple monitoringBlocks
.每个monitoringBlock
只能容纳 1 个 item,但有多个monitoringBlocks
。pollingBlock
should keep processing all the items including the one posted in a while (true)
manner. pollingBlock
应该继续处理所有项目,包括以一段while (true)
方式发布的项目。monitoringBlocks
while occupied should not accept any other messages and these messages should just get deleted without further processing.被占用的monitoringBlocks
块不应该接受任何其他消息,并且这些消息应该被删除而无需进一步处理。monitoringBlock
the message should either be marked as completed or transfer to the next block for processing, this next block is processingBlock
在monitoringBlock
中进行一些处理后,消息应该被标记为完成或者转移到下一个块进行处理,这个下一个块是processingBlock
A brief sample:一个简短的示例:
public Task ExecutePipeline()
{
var block = CreatePollingPipeline();
block.Post((_serviceOne, _serviceTwo));
block.Complete();
return block.Completion;
}
public ActionBlock<(IServiceOne serviceOne, IServiceTwo serviceTwo)> CreatePollingPipeline()
{
var pollingAlertHolder = new BufferBlock<(string input1, string input2)>();
var pollingBlock = new ActionBlock<(IServiceOne serviceOne, IServiceTwo serviceTwo)>(services =>
{
while (true)
{
Console.WriteLine("Posting to alert block");
pollingAlertHolder.Post(("INP1", "INPVAL"));
Thread.Sleep(2000);
Console.WriteLine("Posting to alert block");
pollingAlertHolder.Post(("INP1", "INPVAL"));
Thread.Sleep(2000);
Console.WriteLine("Posting to alert block");
pollingAlertHolder.Post(("INP2", "INPVAL2"));
Thread.Sleep(2000);
Console.WriteLine("Posting to alert block");
pollingAlertHolder.Post(("INP1", "INPVAL"));
Thread.Sleep(2000);
Console.WriteLine("Posting to alert block");
pollingAlertHolder.Post(("INP1", "INPVAL"));
Thread.Sleep(2000);
Console.WriteLine("Posting to alert block");
pollingAlertHolder.Post(("INP2", "INPVAL2"));
Thread.Sleep(2000);
}
});
var monitoringBlock = new TransformBlock<(string input1, string input2), (string input1, string input2)>(inputs =>
{
Console.WriteLine("monitoringBlock started");
Thread.Sleep(5000);
Console.WriteLine("monitoringBlock completed");
return (inputs.input1, inputs.input2);
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1, BoundedCapacity = 1 });
pollingAlertHolder.LinkTo(monitoringBlock, new DataflowLinkOptions() { PropagateCompletion = true },
inputs => inputs.input1 == "INP1" && inputs.input2 == "INPVAL");
pollingAlertHolder.LinkTo(DataflowBlock.NullTarget<(string input1, string input2)>());
var processingBlock = new ActionBlock<(string input1, string input2)>(i =>
{
Console.WriteLine("processingBlock started");
Thread.Sleep(2000);
Console.WriteLine("processingBlock completed");
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1, BoundedCapacity = 1 });
monitoringBlock.LinkTo(processingBlock, new DataflowLinkOptions { PropagateCompletion = true });
return pollingBlock;
}
My question is how do I keep monitoringBlock
occupied until linked processingBlock
finishes its' job?我的问题是如何在链接的processingBlock
完成其工作之前保持monitoringBlock
被占用? I don't want any items to be posted to monitoringBlock
before the message finished the FULL processing cycle.在消息完成完整处理周期之前,我不希望将任何项目发布到monitoringBlock
。
As already mentioned in comments, you can simply encapsulate logic of monitoringBlock
and processingBlock
in one block, for example, you can achieve that via predefined Datablock.Encapsulate
method.正如评论中已经提到的,您可以简单地将monitoringBlock
和processingBlock
的逻辑封装在一个块中,例如,您可以通过预定义的Datablock.Encapsulate
方法来实现。
However, if you don't want to do that, you can use AutoResetEvent
or similar abstraction, and your code could be like this:但是,如果您不想这样做,您可以使用AutoResetEvent
或类似的抽象,您的代码可能是这样的:
AutoResetEvent dataflowEvent = new AutoResetEvent(true);
var bufferBlock = new ActionBLock<(string input1, string input2)>(i =>
{
dataflowEvent.WaitOne();
monitoringBlock.Post(i);
});
var monitoringBlock = new TransformBlock<(string input1, string input2), (string input1, string input2)>(inputs =>
{
Console.WriteLine("monitoringBlock started");
Thread.Sleep(5000);
Console.WriteLine("monitoringBlock completed");
dataflowEvent.Set();
return (inputs.input1, inputs.input2);
},
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 1, BoundedCapacity = 1 });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.