-->

使用BufferBlock的好处 在数据流网络(Benefits of using Buffe

2019-08-01 06:03发布

如果有与使用链接到一个或多个ActionBlocks,比(使用BoundedCapacity)节流以外的BufferBlock相关的益处,我想知道的只是直接发布到ActionBlock(S),而不是(只要节流则不需要)。

Answer 1:

如果你想要做的就是转发从一个块到其他几个项目,你不需要BufferBlock

但也有肯定的地方是有用的情况。 举例来说,如果你有一个复杂的数据流的网络,您可能希望从较小的子网络构建它,在它自己的方法创建的每一个。 而要做到这一点,你需要一些方法来表示一组块。 在这种情况下,你所提到的,返回该单BufferBlock (可能是因为ITargetBlock从法)将是一个简单的解决方案。

其中另一个例子BufferBlock将是有益的是,如果你想送几个源块项目的几个目标块。 如果使用BufferBlock作为中介,你不必每个源块连接到每个目标块。

我敢肯定,有许多其他的例子,你可以使用BufferBlock 。 当然,如果你没有看到任何理由在你的情况来使用它,那就不要。



Answer 2:

为了增加svick的答案,有bufferblocks的另一个好处。 如果你有多个输出链接块,并希望他们之间的平衡,你必须把输出块非贪婪和添加bufferblock处理排队。 我发现下面的例子有用:

从一个链接,现在是死的报价:

这就是我们打算做的事:

  • 一些代码块将使用它的POST(T t)的方法发布数据到BufferBlock。
  • 此BufferBlock被链接到使用LinkTo吨BufferBlock的方法3个ActionBlock实例)。

请注意,BufferBlock不输入数据的不移交副本,它与to.Instead它这样一个目标块only.Here我们期待的是,当一个目标是忙于处理request.It将交由中的所有目标块在其他target.Now让我们参考下面的代码:

static void Main(string[] args)
{
    BufferBlock<int> bb = new BufferBlock<int>();

    ActionBlock<int> a1 = new ActionBlock<int>(a =>
    {
        Thread.Sleep(100);
        Console.WriteLine("Action A1 executing with value {0}", a);
    });

    ActionBlock<int> a2 = new ActionBlock<int>(a =>
    {
        Thread.Sleep(50);
        Console.WriteLine("Action A2 executing with value {0}", a);
    });

    ActionBlock<int> a3 = new ActionBlock<int>(a =>
    {
        Thread.Sleep(50);
        Console.WriteLine("Action A3 executing with value {0}", a);
    });

    bb.LinkTo(a1);
    bb.LinkTo(a2);
    bb.LinkTo(a3);

    Task t = new Task(() =>
        {
            int i = 0;
            while (i < 10)
            {
                Thread.Sleep(50);
                i++;
                bb.Post(i);
            }
        }
    );

    t.Start();
    Console.Read();
}

当被执行时它产生以下输出:

  • 动作A1与值1执行
  • 动作A1与值2执行
  • 动作A1与值3执行
  • 动作A1具有值4执行
  • 动作A1具有值5执行
  • 动作A1具有值6执行
  • 动作A1与值7执行
  • 动作A1具有值8执行
  • 动作A1与值9执行
  • 动作A1与值10执行

这表明,只有一个目标是实际执行中的所有数据,即使它忙(由于Thread.sleep代码(100)有意添加)。为什么?

这是因为所有的目标块默认情况下自然界中的贪婪,甚至缓冲输入时,他们没有能够处理data.To改变这种行为,我们已经在DataFlowBlockOptions贪婪属性设置为false,同时初始化ActionBlock如下图所示。

static void Main(string[] args)
{
    BufferBlock<int> bb = new BufferBlock<int>();
    ActionBlock<int> a1 = new ActionBlock<int>(a =>
        {
            Thread.Sleep(100);
            Console.WriteLine("Action A1 executing with value {0}", a);
        }
        , new DataflowBlockOptions(taskScheduler: TaskScheduler.Default,
            maxDegreeOfParallelism: 1, maxMessagesPerTask: 1,
            cancellationToken: CancellationToken.None,
            //Not Greedy
            greedy: false));

    ActionBlock<int> a2 = new ActionBlock<int>(a =>
        {
            Thread.Sleep(50);
            Console.WriteLine("Action A2 executing with value {0}", a);
        }
        , new DataflowBlockOptions(taskScheduler: TaskScheduler.Default,
            maxDegreeOfParallelism: 1, maxMessagesPerTask: -1,
            cancellationToken: CancellationToken.None,
            greedy: false));
    ActionBlock<int> a3 = new ActionBlock<int>(a =>
        {
            Thread.Sleep(50);
            Console.WriteLine("Action A3 executing with value {0}", a);
        }
        , new DataflowBlockOptions(taskScheduler: TaskScheduler.Default,
            maxDegreeOfParallelism: 1, maxMessagesPerTask: -1,
            cancellationToken: CancellationToken.None,
            greedy: false));

    bb.LinkTo(a1);
    bb.LinkTo(a2);
    bb.LinkTo(a3);

    Task t = new Task(() =>
    {
        int i = 0;
        while (i < 10)
        {
            Thread.Sleep(50);
            i++;
            bb.Post(i);
        }
    });

    t.Start();
    Console.Read();
}

这个程序的输出是:

  • 动作A1与值1执行
  • 行动A2与值3执行
  • 动作A1与值2执行
  • 行动A3与价值6执行
  • 行动A3与价值7执行
  • 行动A3与价值8执行
  • 行动A2具有值5执行
  • 行动A3值为9执行
  • 动作A1具有值4执行
  • 行动A2值为10执行

这清楚地跨预期3个ActionBlock(S)的数据的分布。



Answer 3:

否,第二个例子将不编译一些原因:它只能设定贪婪=假一个“分组”数据流块 - 用于执行块不; 然后它必须通过GroupingDataflowBlockOptions设置 - 不DataflowBlockOptions; 然后它被设置为属性值“{贪婪= FALSE}”不是一个构造符参数。

如果要限制动作框的能力,通过设置DataflowBlockOptions的BoundedCapacity属性的值(虽然作为OP说,他们已经意识到了这个选项)做到这一点。 像这样:

var a1 = new ActionBlock<int>(
            i => doSomeWork(i), 
            new ExecutionDataflowBlockOptions {BoundedCapacity = 1}
        );


文章来源: Benefits of using BufferBlock in dataflow networks