2014-07-14 19 views
-1

我想確定爲什麼我的阻止集合的性能顯得很慢。我的代碼的簡單版本在下面的問題中進行了說明。BlockingCollection.TryTake(object,TimeSpan)應該立即返回新數據嗎?

我的問題在於如果BlockingCollection.TryTake(object,TimeSpan)立即返回新數據?

TimeSpan gridNextTS = new TimeSpan(0, 0, 60); 

if (trPipe.TryTake(out tr, gridNextTS) == false) 

從我的測試看來,數據不會立即返回。這似乎是可能需要的行爲,還是我錯誤地使用它?

詳細的代碼前面的問題:

Consumer/Producer with BlockingCollection appears slow

+2

你是什麼意思的「立即」? (一短,但*完整*程序演示問題將真正幫助。) –

回答

4

簡明基準表明,BlockingCollection<T>呢,其實,進行切換非常迅速,無論供給TryTake超時值。

public async Task BlockingCollectionPerformance() 
{ 
    using (var collection = new BlockingCollection<int>()) 
    { 
     var consumer = Task.Run(() => 
     { 
      var i = 0; 

      while (collection.TryTake(out i, TimeSpan.FromSeconds(2))) 
      { 
       Debug.Print(i.ToString()); 
      } 
     }); 

     var producer = Task.Run(() => 
     { 
      try 
      { 
       for (var i = 0; i < 10; i++) 
       { 
        collection.Add(i); 
       } 
      } 
      finally 
      { 
       collection.CompleteAdding(); 
      } 
     }); 

     await Task.WhenAll(producer, consumer); 
    } 
} 

以上完成在我的盒子~3毫秒。

更具體地講,雖然,迅速TryTake回報每當一個項目添加到集合(和TryTake回報true),當你在阻擋收集調用CompleteAdding(在這種情況下沒有點等待出超時,TryTake返回false)。這可以通過保持消費者搬起石頭砸自己的腳阻止超過所需的時間,如果你永遠不會調用在這種情況下TryTakeCompleteAdding將返回false之前等待出十足的超時時間。

+0

道歉了'TryAdd's在原來的版本:這是一個錯字。 –

+0

我每天都會收到數十萬次添加事件。我應該在每次之後致電CompleteAdding嗎? – ManInMoon

+0

@ ManInMoon,只有當你使用數十萬個阻塞集合(你可能不會)。 CompleteAdding只需調用一次 - 當您完成集合並且不會再添加它時。主要觀點是 - 阻止收集速度很快(因爲它的作用),所以在其他地方尋找你的瓶頸。 –