.net TPL数据流:创建自定义拆分块

.net TPL数据流:创建自定义拆分块,.net,task-parallel-library,tpl-dataflow,.net,Task Parallel Library,Tpl Dataflow,只需要在dataflow库的帮助下创建自定义splitblock,dataflow库是.Net中TPL的一部分 我想要实现的只是一个简单的自定义块,它接受一个输入并将其拆分为多个转换块。这是过滤数据所必需的,在这里我可以记录否定的条目并继续使用好的条目 根据我的需要,将输入分成两个不同的输出就足够了。类标题应该如下所示 public abstract class SplitBlock<TInput, TOutputLeft, TOutputRight> 公共抽象类拆分块 我的问题

只需要在dataflow库的帮助下创建自定义splitblock,dataflow库是.Net中TPL的一部分

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

根据我的需要,将输入分成两个不同的输出就足够了。类标题应该如下所示

public abstract class SplitBlock<TInput, TOutputLeft, TOutputRight>
公共抽象类拆分块
我的问题是我真的不知道如何继续下去。我只知道我需要两个转换块:

var leftBlock  = new TransformBlock<TInput, TOutputLeft>(...)
var rightblock = new TransformBlock<TInput, TOutputRight>(...)
var leftBlock=new TransformBlock(…)
var rightblock=新转换块(…)
在我所有的尝试中,我最终得到了多个ITargetBlock来存储左、右块的输入,但这不可能是正确的,不是吗


我很感激您能给我的每一个提示。

我将从思考该类的通用接口应该是什么样子开始。我认为最简单的解决办法是:

public class SplitBlock<TInput, TOutputLeft, TOutputRight>
{
    public ITargetBlock<TInput> Input { get; }
    public ISourceBlock<TOutputLeft> LeftOutput { get; }
    public ISourceBlock<TOutputRight> RightOutput { get; }
}
(这假设左侧和右侧变换可以同时处理相同的输入。)

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

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)))
    {}
}
公共类拆分块
{
私有操作块输入;
专用缓冲块输出;
专用缓冲块输出;
公共ITargetBlock输入{get{return Input;}}
公共ISourceBlock LeftOutput{get{return LeftOutput;}}
公共ISourceBlock RightOutput{get{return RightOutput;}}
公共分块(
Func(组合变换)
{
输入=新动作块(
值=>
{
var结果=组合转换(值);
leftOutput.Post(result.Item1);
rightOutput.Post(结果项2);
});
leftOutput=新的缓冲块();
rightOutput=新的缓冲块();
//TODO正确处理输入中的故障
input.Completion.ContinueWith(
_ =>
{
leftOutput.Complete();
rightOutput.Complete();
});
}
公共分块(
Func leftTransform,
Func(右变换)
:this(x=>Tuple.Create(leftTransform(x),rightTransform(x)))
{}
}

非常感谢。我拿了你的第一张素描,写了一些东西。效果相当不错。
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)))
    {}
}