2016-02-28 62 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