經過一番研究,我正在尋求任何有關如何有效地從Concurrent集合中刪除兩個項目的反饋。我的情況涉及通過UDP傳入的消息,這些消息當前正在放入BlockingCollection中。一旦集合中有兩個用戶,我需要安全地接收兩個用戶並處理它們。我見過幾種不同的技術,包括下面列出的一些想法。我目前的實施情況如下,但我認爲有一個更清晰的方法可以做到這一點,同時確保用戶按兩組進行處理。這是這種情況下唯一的限制。.Net BlockingCollection.Take(2):一次安全刪除兩個項目
實施現狀:
private int userQueueCount = 0;
public BlockingCollection<User> UserQueue = new BlockingCollection<User>();
public void JoinQueue(User u)
{
UserQueue.Add(u);
Interlocked.Increment(ref userQueueCount);
if (userQueueCount > 1)
{
IEnumerable<User> users = UserQueue.Take(2);
if(users.Count==2) {
Interlocked.Decrement(ref userQueueCount);
Interlocked.Decrement(ref userQueueCount);
... do some work with users but if only one
is removed I'll run into problems
}
}
}
我想要做的就是這樣的事情,但我目前不能測試這在生產形勢,以確保其完整性。
Parallel.ForEach(UserQueue.Take(2), (u) => { ... });
或者更好的是:
public void JoinQueue(User u)
{
UserQueue.Add(u);
// if needed? increment
Interlocked.Increment(ref userQueueCount);
UserQueue.CompleteAdding();
}
然後實現這個地方:
Task.Factory.StartNew(() =>
{
while (userQueueCount > 1) OR (UserQueue.Count > 1) If it's safe?
{
IEnumerable<User> users = UserQueue.Take(2);
... do stuff
}
});
這樣做的問題是,我不知道我可以保證,條件之間(計> 1)和Take(2),我確保UserQueue至少有兩個項目要處理?傳入的UDP消息是並行處理的,所以我需要一種方法來安全地從兩個成對的Blocking/Concurrent Collection中取出項目。
有沒有更好/更安全的方法來做到這一點?
修評論: 這個問題的intented目標實際上只是在.NET 4.0中實現的加工項目穩定/線程安全的方法掀起了併發收集的。它不一定非常漂亮,它只需要在並行環境中的無序對中處理項目時保持穩定。
有什麼阻止你將它們擺在首位添加爲元組? – Brunner
你的代碼*不太可能*是線程安全的 - 對於許多單獨的同步調用,所以很難證明它的行爲正確。 –
'Take(2)'正在調用LINQ方法,該方法不會將它們從BlockingCollection中移除。你必須按照他們添加的順序將它們配對嗎?例如,如果集合有a,b,c,d可以由一個線程處理a&c和另一個處理b&d,或者您必須處理&b然後c&d? –