2011-04-30 24 views
12

我需要一個不允許重複的共同集合(在BlockingCollection中用作生產者/消費者)。 我不需要嚴格的元素順序。 從另一方面,我想盡量減少元素「生活」收集的最大時間。即收集一定不能是LIFO,理想情況下它應該是FIFO。如何創建不重複的ConcurrentQueue?

那麼我會說,我需要ConcurrentQueue沒有重複允許,但ConcurrentBag沒有重複也可以工作。

爲什麼C#不包含這樣的東西,可能有人已經創建了它?

這個問題我剛纔的問題的結果What type of IProducerConsumerCollection<T> to use for my task?

+5

C#只是一種語言,你必須尋找一個庫來獲得這樣的功能。像.NET框架一樣,ConcurrentQueue/Bag的主頁。沒有人考慮過這樣寫代碼,它註定要失敗。因爲你無法準確預測生產者何時生產和消費者消費。確定何時消除重複數據大致類似於根據Random.Next()的返回值做出決定。無論什麼原因你必須實現這樣的事情:它註定要失敗。 – 2011-05-01 00:01:19

+0

我不明白爲什麼它註定要失敗。我可以使用ConcurrentDictionary來模擬Set(我將只使用key,value將始終爲null)。我不想消除重複。應該沒有重複。 – javapowered 2011-05-01 07:08:03

+0

此外,「堅果殼中的C#」指出可以編寫併發堆棧:「但是,如果您編寫了自己的併發集合以禁止重複,但是如果元素已經存在,則會使TryAdd返回false(例如,如果您寫了併發集合)「 – javapowered 2011-05-01 09:13:11

回答

1

那麼,如果你嚴格想有沒有重複,你需要「設置」。例如NHibernate使用Iesi.Collections來提供這樣的功能。以Iesi爲例,您可以圍繞提供的'Set'類(DictionarySet,HashSet,SortedSet)構建自己的功能。來源:http://www.codeproject.com/KB/recipes/sets.aspx

+1

.Net確實有一個'HashSet '。據我所知,NHibernate使用'Iesi.Collections'作爲'ISet '(它在.Net庫中沒有好的選擇)。 – svick 2011-05-01 00:42:28

+0

是的,新的.net 3.5及更高版本。 – 2011-05-01 00:43:51

3

沒有內置的.Net庫將這組規則集合在一起。你有三個選擇:

  1. 寫自己的集合類
  2. 使用兩個集合:編寫使用一個ConcurrentQueue和任何基於集收集的自定義類,自動檢查重複;有添加到設置運行,如果成功,添加到ConcurrentQueue;每添加/刪除將添加到這兩個集合時成功
  3. 使用ConcurrentQueue但遍歷整個列表檢查重複

最後兩個是不是很有效(一個內存,其他與CPU, I/O,鎖定)並且由於需要顯式鎖定而變得混亂,但是會完成任務。他們會更快實施,但如果權衡不符合您的要求,您將不得不選擇#1選項。

-3

您可以簡單地使用ConcurrentQueue,並在致電Enqueue之前通過調用ConcurrentQueue.Contains<>方法來檢查數據是否在隊列中。我猜Contains<>擴展方法是相當不錯的優化。

編輯: 正如其他人所指出的那樣,這個工作將你必須使用一個鎖定機制,如圍繞Contains<>方法互斥等和Enqueue方法是這樣的:

get mutex 
if not Contains<> 
{ 
    Enqueue 
} 
release mutex 
+3

我認爲這是行不通的,因爲競態條件可能允許另一個線程在調用Contains和Enqueue之間入隊一個「相等」的對象。我們真的需要一個ConcurrentSet <>來完成這項工作。 – ALEXintlsos 2012-06-01 21:32:27

+0

然後在關鍵代碼周圍添加一個互斥... – Chimera 2012-06-01 22:17:28

+2

...在這種情況下,您不需要併發版本的隊列對象。我認爲原始的海報正在尋找一種原子級防止重複的ConcurrentSet。 – ALEXintlsos 2012-06-04 15:26:13