gpt4 book ai didi

c# - 我如何发出数据流完成的信号?

转载 作者:行者123 更新时间:2023-11-30 14:27:11 25 4
gpt4 key购买 nike

我有一个类使用 TPL 数据流实现由 3 个步骤组成的数据流。

在构造函数中,我将步骤创建为 TransformBlock,并使用 LinkTo 将它们链接起来,并将 DataflowLinkOptions.PropagateCompletion 设置为 true。该类公开了一个方法,该方法通过在第一步调用 SendAsync 来启动工作流。该方法返回工作流最后一步的“完成”属性。

目前,工作流中的步骤似乎按预期执行,但最后一步永远不会完成,除非我对其明确调用 Complete。但是这样做会使工作流程短路并且没有执行任何步骤吗?我做错了什么?

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();
}
}

最佳答案

链接步骤时,您需要传递带有 PropagateCompletion 的 DataflowLinkOptions属性设置为 true 以传播完成和错误。一旦你这样做了,调用Complete()在第一个 block 上将完成传播到下游 block 。

一旦 block 收到完成事件,它就会完成处理,然后通知其链接的下游目标。

这样您就可以将所有数据发布到第一步并调用 Complete() .只有当所有上游 block 都完成时,最后一个 block 才会完成。

例如,

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 默认情况下不是真的,因为在更复杂的场景(例如非线性流或动态变化的流)中,您不希望自动传播完成和错误。如果您想在不终止整个流程的情况下处理错误,您可能还想避免自动完成。

当 TPL Dataflow 处于测试阶段时,默认 true 但这在 RTM 上发生了变化

更新

代码永远不会完成,因为最后一步是 TransformBlock没有链接目标来接收其输出。这意味着即使该 block 收到了完成信号,它还没有完成所有的工作并且不能改变它自己的完成状态。

将其更改为 ActionBlock<object>解决了这个问题。

关于c# - 我如何发出数据流完成的信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33518074/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com