2016-02-28 31 views
1

数据流库有这个选项我试图理解:ExecutionDataflowBlockOptions.SingleProducerConstrainedTPL数据流 - 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 
    } 
} 

回答

3

此标志的目的不是强制执行是否有单个生产者。反之。只有在you表明只有一个生产者时,您才可以进行优化,因此代码无需执行该操作。

设置此标志时,某些块可以删除锁定和同步代码及其开销。但只有你确保有一个单一的制片人。如果你不这样做,可能会有竞争条件,你可能确实会失去讯息。

“如果使用该块的代码可以保证它一次只能由一个生产者(例如,链接到该块的源)使用,则该属性应该只设置为true,这意味着像邮政,完整,故障和OfferMessage将永远不会被同时调用。某些块可以选择在知识资本是只会有一个制片人在同一时间,以提供更好的性能。

ExecutionDataflowBlockOptions.SingleProducerConstrained Property

+0

所以,如果我乱这一点我不能指望程序通知我......考虑到这样的代码将通知您的种族违规似乎不理想:var list = new List (); Parallel.For(0,100,j => Parallel.For(0,100,i => list.Add(i)));感谢您的高举。 –

+0

@TimHauser其实..我不会指望通知你的代码。它可能很容易破坏你的名单。该标志的目的是消除完全检查的开销。如果你不能确保你不应该使用该标志。 – i3arnon