数据流库具有我尝试了解的此选项: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
}
}
最佳答案
该标志的目的不是强制执行是否只有一个生产者。反之。仅当您声明只有一个生产者时才可以进行优化,因此代码无需强制执行。
设置此标志时,某些块可以删除锁定和同步代码及其开销。但前提是您要确保只有一个生产者。如果您不这样做,则可能存在比赛条件,并且确实可能会丢失消息。
“仅当使用该块的代码可以保证一次只能由一个生产者(例如,链接到该块的源)使用该属性时,才应将此属性设置为true,这意味着像Post,Complete,Fault,和OfferMessage
永远不会被同时调用。某些块可能会选择利用一个知识,即一次只有一个生产者,以提供更好的性能。”
来自ExecutionDataflowBlockOptions.SingleProducerConstrained Property
关于c# - TPL数据流-ExecutionDataflowBlockOptions.SingleProducerConstrained,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35683767/