固定サイズの FIFO キューにプロデューサー/コンシューマー パターンを実装する必要があります。ConcurrentQueue のラッパー クラスがこれで機能する可能性があると思いますが、完全にはわかりません (以前に ConcurrentQueue を使用したことがありません)。これのひねりは、キューが固定数のアイテム (私の場合は文字列) のみを保持する必要があることです。私のアプリケーションには、1 つのプロデューサー タスク/スレッドと 1 つのコンシューマー タスク/スレッドがあります。私の消費者タスクが実行されると、その時点でキューに存在するすべてのアイテムをキューから取り出して処理する必要があります。
価値のあることとして、消費者によるキューに入れられたアイテムの処理は、100% 信頼できない Web アプリに SOAP 経由でアイテムをアップロードすることに他なりません。接続を確立できない場合、または SOAP 呼び出しの呼び出しが失敗した場合は、それらの項目を破棄して、キューに戻って詳細を確認する必要があります。SOAP のオーバーヘッドのため、1 回の SOAP 呼び出しで送信できるキューからの項目数を最大化しようとしました。
場合によっては、消費者がアイテムを削除して処理するよりも、生産者がアイテムを追加する方が速い場合があります。キューがすでにいっぱいで、プロデューサーが別のアイテムを追加する必要がある場合、キューのサイズが固定されたままになるように、新しいアイテムをキューに入れ、最も古いアイテムをデキューする必要があります。基本的に、生成された最新のアイテムを常にキューに保持する必要があります (コンシューマーが現在前のアイテムを処理しているため、一部のアイテムが消費されないことを意味する場合でも)。
キュー内のアイテムが固定されている場合にプロデューサーが数を維持することに関して、この質問から1つの潜在的なアイデアを見つけました。
新しいエンキュー時に古い値を自動的にデキューする固定サイズのキュー
私は現在、次のような Enqueue() メソッドを使用して ConcurrentQueue の周りにラッパー クラス (その回答に基づく) を使用しています。
public class FixedSizeQueue<T>
{
readonly ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
public int Size { get; private set; }
public FixedSizeQueue(int size)
{
Size = size;
}
public void Enqueue(T obj)
{
// add item to the queue
queue.Enqueue(obj);
lock (this) // lock queue so that queue.Count is reliable
{
while (queue.Count > Size) // if queue count > max queue size, then dequeue an item
{
T objOut;
queue.TryDequeue(out objOut);
}
}
}
}
次のように、キューにサイズ制限のあるこのクラスのインスタンスを作成します。
FixedSizeQueue<string> incomingMessageQueue = new FixedSizeQueue<string>(10); // 10 item limit
プロデューサー タスクを開始すると、キューがいっぱいになり始めます。私の Enqueue() メソッドのコードは、アイテムを追加するとキューの数が最大サイズを超えたときにキューから最も古いアイテムを削除することに関して、適切に機能しているようです。ここで、アイテムをデキューして処理する消費者タスクが必要ですが、ここで私の頭が混乱します。ある時点でキューのスナップショットを取得し、処理のためにすべての項目をデキューするコンシューマ用の Dequeue メソッドを実装する最良の方法は何ですか (プロデューサーは、このプロセス中にまだ項目をキューに追加している可能性があります)。