TPL DataFlow:创建自定义拆分块(TPL DataFlow: creating a custom splitblock)

编程入门 行业动态 更新时间:2024-10-28 19:20:17
TPL DataFlow:创建自定义拆分块(TPL DataFlow: creating a custom splitblock)

在数据流库的帮助下创建自定义拆分块只需要一些帮助,该库是.Net中TPL的一部分。

我想要实现的只是一个简单的自定义块,它接受输入并将其拆分为多个transformblock。 这是过滤数据所必需的,我可以在其中记录否定条目并继续使用好的条目。

根据我的需要,它应该足以将输入分成两个不同的输出。 类头应该看起来像这样......

public abstract class SplitBlock<TInput, TOutputLeft, TOutputRight>

我的问题是,我真的不知道该怎么做。 我所知道的是我需要两个TransformBlocks:

var leftBlock = new TransformBlock<TInput, TOutputLeft>(...) var rightblock = new TransformBlock<TInput, TOutputRight>(...)

在我的所有尝试中,我最终有多个ITargetBlocks用于存储左右块的输入,但这不能正确,可以吗?

我很感激你能给予的每一个暗示。

just need some help creating a custom splitblock with the help of the dataflow library which is part of the TPL in .Net.

All I want to achieve is a simple custom block that takes an input and splits this to multiple transformblocks. This is needed for filtering data, where I could log negativ entries and go on with the good one.

For my needs it should be enough to split the input to two different outputs. The class header should look something like this...

public abstract class SplitBlock<TInput, TOutputLeft, TOutputRight>

My problem is that I dont realy know how to go on. All I know is that I need two TransformBlocks:

var leftBlock = new TransformBlock<TInput, TOutputLeft>(...) var rightblock = new TransformBlock<TInput, TOutputRight>(...)

In all my tries I ended up having multiple ITargetBlocks for storing the input of the left and right block, but this cant be right, can it?

I appreciate every hint that you can give.

最满意答案

我将首先考虑该类的通用接口应该是什么样子。 我认为最简单的解决方案是:

public class SplitBlock<TInput, TOutputLeft, TOutputRight> { public ITargetBlock<TInput> Input { get; } public ISourceBlock<TOutputLeft> LeftOutput { get; } public ISourceBlock<TOutputRight> RightOutput { get; } }

由此,实现自然地实现:一个输入块连接到两个输出块。 唯一的问题是实际处理是应该在输出块中完成(如您在两个TransformBlock建议的那样)还是在输入块中。

如果你想在输出块中进行处理,输入块可以是一个ActionBlock ,它将输入发送到两个输出,输出将是TransformBlock ,如你所建议的那样。

public class SplitBlock<TInput, TOutputLeft, TOutputRight> { private ActionBlock<TInput> input; private TransformBlock<TInput, TOutputLeft> leftOutput; private TransformBlock<TInput, TOutputRight> rightOutput; public ITargetBlock<TInput> Input { get { return input; } } public ISourceBlock<TOutputLeft> LeftOutput { get { return leftOutput; } } public ISourceBlock<TOutputRight> RightOutput { get { return rightOutput; } } public SplitBlock( Func<TInput, TOutputLeft> leftTransform, Func<TInput, TOutputRight> rightTransform) { input = new ActionBlock<TInput>( x => { leftOutput.Post(x); rightOutput.Post(x); }); leftOutput = new TransformBlock<TInput, TOutputLeft>(leftTransform); rightOutput = new TransformBlock<TInput, TOutputRight>(rightTransform); // TODO handle fault in input correctly input.Completion.ContinueWith( _ => { leftOutput.Complete(); rightOutput.Complete(); }); } }

(这假设左右变换可以同时处理相同的输入。)

另一方面,如果你想在输入块中执行处理(这对我来说更有意义),那么你可以将ActionBlock作为输入,将BufferBlock作为输出,输入块处理输入然后发送结果到输出块:

public class SplitBlock<TInput, TOutputLeft, TOutputRight> { private ActionBlock<TInput> input; private BufferBlock<TOutputLeft> leftOutput; private BufferBlock<TOutputRight> rightOutput; public ITargetBlock<TInput> Input { get { return input; } } public ISourceBlock<TOutputLeft> LeftOutput { get { return leftOutput; } } public ISourceBlock<TOutputRight> RightOutput { get { return rightOutput; } } public SplitBlock( Func<TInput, Tuple<TOutputLeft, TOutputRight>> combinedTransform) { input = new ActionBlock<TInput>( value => { var result = combinedTransform(value); leftOutput.Post(result.Item1); rightOutput.Post(result.Item2); }); leftOutput = new BufferBlock<TOutputLeft>(); rightOutput = new BufferBlock<TOutputRight>(); // TODO handle fault in input correctly input.Completion.ContinueWith( _ => { leftOutput.Complete(); rightOutput.Complete(); }); } public SplitBlock( Func<TInput, TOutputLeft> leftTransform, Func<TInput, TOutputRight> rightTransform) : this(x => Tuple.Create(leftTransform(x), rightTransform(x))) {} }

I would start with thinking about how the general interface of that class should look like. I think the simplest solution would be something like:

public class SplitBlock<TInput, TOutputLeft, TOutputRight> { public ITargetBlock<TInput> Input { get; } public ISourceBlock<TOutputLeft> LeftOutput { get; } public ISourceBlock<TOutputRight> RightOutput { get; } }

With that, the implementation follows naturally: one input block connected to two output blocks. The only question is whether the actual processing should be done in the output blocks (like you suggested with your two TransformBlocks) or in the input block.

If you want to have processing in the output blocks, the input block can be an ActionBlock that sends the input to both outputs and the outputs will be TransformBlocks, as you suggested.

public class SplitBlock<TInput, TOutputLeft, TOutputRight> { private ActionBlock<TInput> input; private TransformBlock<TInput, TOutputLeft> leftOutput; private TransformBlock<TInput, TOutputRight> rightOutput; public ITargetBlock<TInput> Input { get { return input; } } public ISourceBlock<TOutputLeft> LeftOutput { get { return leftOutput; } } public ISourceBlock<TOutputRight> RightOutput { get { return rightOutput; } } public SplitBlock( Func<TInput, TOutputLeft> leftTransform, Func<TInput, TOutputRight> rightTransform) { input = new ActionBlock<TInput>( x => { leftOutput.Post(x); rightOutput.Post(x); }); leftOutput = new TransformBlock<TInput, TOutputLeft>(leftTransform); rightOutput = new TransformBlock<TInput, TOutputRight>(rightTransform); // TODO handle fault in input correctly input.Completion.ContinueWith( _ => { leftOutput.Complete(); rightOutput.Complete(); }); } }

(This assumes that left and right transforms can process the same input at the same time.)

On the other hand, if you wanted to perform the processing in the input block (which makes more sense to me), then you could have ActionBlock as input and BufferBlocks as outputs, with the input block processing the input and then sending the results to the output blocks:

public class SplitBlock<TInput, TOutputLeft, TOutputRight> { private ActionBlock<TInput> input; private BufferBlock<TOutputLeft> leftOutput; private BufferBlock<TOutputRight> rightOutput; public ITargetBlock<TInput> Input { get { return input; } } public ISourceBlock<TOutputLeft> LeftOutput { get { return leftOutput; } } public ISourceBlock<TOutputRight> RightOutput { get { return rightOutput; } } public SplitBlock( Func<TInput, Tuple<TOutputLeft, TOutputRight>> combinedTransform) { input = new ActionBlock<TInput>( value => { var result = combinedTransform(value); leftOutput.Post(result.Item1); rightOutput.Post(result.Item2); }); leftOutput = new BufferBlock<TOutputLeft>(); rightOutput = new BufferBlock<TOutputRight>(); // TODO handle fault in input correctly input.Completion.ContinueWith( _ => { leftOutput.Complete(); rightOutput.Complete(); }); } public SplitBlock( Func<TInput, TOutputLeft> leftTransform, Func<TInput, TOutputRight> rightTransform) : this(x => Tuple.Create(leftTransform(x), rightTransform(x))) {} }

更多推荐

本文发布于:2023-07-20 06:15:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1195199.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:自定义   DataFlow   TPL   splitblock   custom

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!