.net TPL数据流:创建自定义拆分块
只需要在dataflow库的帮助下创建自定义splitblock,dataflow库是.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> 公共抽象类拆分块 我的问题
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)))
{}
}