例如,我有三个街区:
Buffer -> Transform -> Action
我正在运行webapi服务,它将请求中的数据带到缓冲区块。如何创建这样一个将永远运行的管道,而无需在Action块中调用Completion()并停止整个管道。
答案 0 :(得分:4)
Dataflow没有一个很好的解决方案来获取某个输入的管道输出(因为它支持的不仅仅是简单的管道)。
你可以做些什么来创建一个TaskCompletionSource<T>
并将其与输入一起发送到管道。管道中的每个块都将其发送到下一个块,最后一个块调用其SetResult()
。
然后,将输入发送到管道的代码可以await
TaskCompletionSource
的{{1}}来等待管道的输出。
答案 1 :(得分:3)
如果您需要在应用程序的生命周期内保留管道,而不仅仅是请求,您可以使用静态类来保存它。没有必要在动作块上调用完成。根据您的需求,另一个选择是分离应用程序和处理管道。这些可以由数据库消息队列分开,也可以由单独的服务器端应用程序分隔。
@svick使用TaskCompletionSource确定管道何时完成特定项目有一个好处。将所有内容放在一起这是一个可能有用的快速示例:
public class Controller {
public async Task<int> PostToPipeline(int inputValue) {
var message = new MessageIn(inputValue);
MyPipeline.InputBuffer.Post(message);
return await message.Completion.Task;
}
}
public class MessageIn {
public MessageIn(int value) {
InputValue = value;
Completion = new TaskCompletionSource<int>();
}
public int InputValue { get; set; }
public TaskCompletionSource<int> Completion { get; set; }
}
public class MessageProcessed {
public int ProcessedValue { get; set; }
public TaskCompletionSource<int> Completion { get; set; }
}
public static class MyPipeline {
public static BufferBlock<MessageIn> InputBuffer { get; private set; }
private static TransformBlock<MessageIn, MessageProcessed> transform;
private static ActionBlock<MessageProcessed> action;
static MyPipeline() {
BuildPipeline();
LinkPipeline();
}
static void BuildPipeline() {
InputBuffer = new BufferBlock<MessageIn>();
transform = new TransformBlock<MessageIn, MessageProcessed>((Func<MessageIn, MessageProcessed>)TransformMessage, new ExecutionDataflowBlockOptions() {
MaxDegreeOfParallelism = Environment.ProcessorCount,
BoundedCapacity = 10
});
action = new ActionBlock<MessageProcessed>((Action<MessageProcessed>)CompletedProcessing, new ExecutionDataflowBlockOptions() {
MaxDegreeOfParallelism = Environment.ProcessorCount,
BoundedCapacity = 10
});
}
static void LinkPipeline() {
InputBuffer.LinkTo(transform, new DataflowLinkOptions() { PropagateCompletion = true });
transform.LinkTo(action, new DataflowLinkOptions() { PropagateCompletion = true });
}
static MessageProcessed TransformMessage(MessageIn message) {
return new MessageProcessed() {
ProcessedValue = message.InputValue++,
Completion = message.Completion
};
}
static void CompletedProcessing(MessageProcessed message) {
message.Completion.SetResult(message.ProcessedValue);
}
}
有几种方法可以协调管道中特定作业的完成;等待完成源可能是满足您需求的最佳方法。