いくつかの調査を行った後、Concurrent コレクションから 2 つのアイテムを効果的に削除する方法に関するフィードバックに頼っています。私の状況には、現在 BlockingCollection に配置されている UDP 経由の受信メッセージが含まれます。コレクションに 2 人のユーザーが含まれたら、安全に 2 人のユーザーを取得して処理する必要があります。以下にリストされているいくつかのアイデアを含む、いくつかの異なる手法を見てきました。私の現在の実装は以下のとおりですが、Users が 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
}
});
これに関する問題は、条件 (Count > 1) と、UserQueue に処理するアイテムが少なくとも 2 つあることを確認している Take(2) の間で保証できるかどうかわからないことです。着信 UDP メッセージは並行して処理されるため、ブロッキング/同時コレクションからアイテムを 2 つずつ安全にプルする方法が必要です。
これを行うためのより良い/安全な方法はありますか?
改訂されたコメント: この質問の意図した目標は、.Net 4.0 の並行コレクションから項目を処理する安定した/スレッドセーフな方法を実現することです。きれいである必要はありません。並列環境で順序付けされていない 2 のペアでアイテムを処理するタスクで安定している必要があります。