简体   繁体   English

如何表示我的数据流完成?

[英]How do I signal completion of my dataflow?

I've got a class the implements a dataflow composed of 3 steps using TPL Dataflow. 我有一个类实现了一个使用TPL Dataflow由3个步骤组成的数据流。

In the constructor I create the steps as TransformBlocks and link them up using LinkTo with DataflowLinkOptions.PropagateCompletion set to true. 在构造函数中,我将步骤创建为TransformBlocks并使用LinkTo将其链接起来,并将DataflowLinkOptions.PropagateCompletion设置为true。 The class exposes a single method which kicks of the workflow by calling SendAsync on the 1st step. 该类公开了一个方法,通过在第一步调用SendAsync来启动工作流。 The method returns the "Completion" property of the final step of the workflow. 该方法返回工作流程最后一步的“完成”属性。

At the moment the steps in the workflow appear to execute as expected but final step never completes unless I explicitly call Complete on it. 目前,工作流中的步骤似乎按预期执行,但最终步骤永远不会完成,除非我明确地在其上调用Complete。 But doing that short-circuits the workflow and none of the steps are executed? 但这样做会使工作流程短路并且没有执行任何步骤? What am I doing wrong? 我究竟做错了什么?

public class MessagePipeline {
   private TransformBlock<object, object> step1;
   private TransformBlock<object, object> step2;
   private TransformBlock<object, object> step3;

   public MessagePipeline() {
      var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
      step1 = new TransformBlock<object, object>(
        x => {
        Console.WriteLine("Step1...");
        return x;
      });
      step2 = new TransformBlock<object, object>(
        x => {
        Console.WriteLine("Step2...");
        return x;
      });
      step3 = new TransformBlock<object, object>(
        x => {
        Console.WriteLine("Step3...");
        return x;
      });

      step1.LinkTo(step2, linkOptions);
      step2.LinkTo(step3, linkOptions);
   }

   public Task Push(object message) {
      step1.SendAsync(message);
      step1.Complete();
      return step3.Completion;
   }
}
...
public class Program {
  public static void Main(string[] args) {
    var pipeline = new MessagePipeline();
    var result = pipeline.Push("Hello, world!");
    result.ContinueWith(_ => Console.WriteLine("Completed"));
    Console.ReadLine();
  }
}

When you link the steps, you need to pass a DataflowLinkOptions with the the PropagateCompletion property set to true to propagate both completion and errors. 链接这些步骤时,需要传递DataflowLinkOptions,并将PropagateCompletion属性设置为true以传播完成和错误。 Once you do that, calling Complete() on the first block will propagete completion to downstream blocks. Complete() ,在第一个块上调用Complete()将完成下游块的完成。

Once a block receives the completion event, it finishes processing then notifies its linked downstream targets. 一旦块接收到完成事件,它就完成处理,然后通知其链接的下游目标。

This way you can post all your data to the first step and call Complete() . 这样您就可以将所有数据发布到第一步并调用Complete() The final block will only complete when all upstream blocks have completed. 最后一个块仅在所有上游块完成后才会完成。

For example, 例如,

var linkOptions=new DataflowLinkOptions { PropagateCompletion = true};
myFirstBlock.LinkTo(mySecondBlock,linkOptions);
mySecondBlock.LinkTo(myFinalBlock,linkOptions);

foreach(var message in messages)
{
    myFirstBlock.Post(message);
}
myFirstBlock.Complete();
......
await myFinalBlock.Completion;

PropagateCompletion isn't true by default because in more complex scenarios (eg non-linear flows, or dynamically changing flows) you don't want completion and errors to propagate automatically. 默认情况下,PropagateCompletion不成立,因为在更复杂的场景中(例如非线性流或动态更改流),您不希望完成和错误自动传播。 You may also want to avoid automatic completion if you want to handle errors without terminating the entire flow. 如果要在不终止整个流程的情况下处理错误,您可能还希望避免自动完成。

Way back when TPL Dataflow was in beta the default was true but this was changed on RTM 遥想当年TPL数据流在测试默认真实的,但是这是对RTM改变

UPDATE UPDATE

The code never completes because the final step is a TransformBlock with no linked target to receive its output. 代码永远不会完成,因为最后一步是TransformBlock ,没有链接目标来接收其输出。 This means that even though the block received the completion signal, it hasn't finished all its work and can't change its own Completion status. 这意味着即使块收到完成信号,它也没有完成所有工作,也无法改变自己的完成状态。

Changing it to an ActionBlock<object> removes the issue. 将其更改为ActionBlock<object>消除此问题。

您需要明确调用Complete。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM