TPL Dataflow - ExecutionDataflowBlockOptions.SingleProducerC

本文关键字:SingleProducerC ExecutionDataflowBlockOptions Dataflow TPL | 更新日期: 2023-09-27 18:36:39

数据流库有这个选项,我试图理解:ExecutionDataflowBlockOptions.SingleProducerConstrained

我对其功能进行了测试。 令我惊讶的是,它似乎会丢弃消息。 为什么这不会引发异常而不是丢弃消息?

[TestMethod]
public void ExecutionDataflowOptions_SingleProducerConstrained()
{
    //The failure does not happen each time, so I run it a few times.
    for (int iter = 0; iter < 100; iter++) 
    {
        //Create two buffers and one action block.
        var buffer1 = new BufferBlock<int>();
        var buffer2 = new BufferBlock<int>();
        var input = new List<int>(); //A reference type, to be changed by the action block
        var transform = new ActionBlock<int>(i => input.Add(i)
            , new ExecutionDataflowBlockOptions() { SingleProducerConstrained = true });
        buffer1.LinkTo(transform);
        buffer2.LinkTo(transform);
        //Add two elements, one from each buffer
        buffer1.Post(1);
        buffer2.Post(2);
        Thread.Sleep(100); //added in test, see end
        //Violate the SingleProducerConstrained parameter
        Parallel.For(0, 100, i => //0, 1, 2 
        {
            var isAccepted1 = buffer1.Post(i);
            var isAccepted2 = buffer2.Post(i);
            if (!isAccepted1 || !isAccepted2)
                throw new Exception(); //This does not error.
        });
        //Ensure the transform completes (likely not necessary)
        transform.Complete();
        transform.Completion.Wait();
        //Account for all the items: 200 from the Parallel.For + 2 initial
        if (202 != buffer1.Count + buffer2.Count + transform.InputCount + input.Count)
            throw new Exception(); //Debug point
    }
}

TPL Dataflow - ExecutionDataflowBlockOptions.SingleProducerC

此标志的目的不是强制是否存在单个生产者。相反。它用于优化,只有当您声明只有一个生产者时才能执行,因此代码不需要强制执行。

设置此标志时,某些块可以删除锁定和同步代码及其开销。但前提是您确保只有一个制片人。如果不这样做,可能会有竞争条件,并且确实可能会丢失消息。

"只有当使用该块的代码可以保证它一次只能由一个生产者(例如链接到块的源)使用时,此属性才应设置为 true,这意味着 Post、Complete、Fault 和 OfferMessage 等方法永远不会同时调用。一些区块可能会选择利用一次只有一个生产者的知识,以提供更好的性能。

From ExecutionDataflowBlockOptions.SingleProducerConstrained Property