Web アプリケーションの一部として IIS にシングルトン サービス クラスがあります (サービスはデータ キャッシュの理由でシングルトンになります)。サービスにリクエストを行うブラウザ クライアントは、次の 3 つの結果のいずれかを取得できます。
1) キャッシュにデータがあり、データの有効期限が切れていない (古い) - このデータを返します。とても早い。2) キャッシュされたデータの有効期限が切れていますが、別の要求が既にデータベースを照会しています。キャッシュされたデータを返しました。3) キャッシュされたデータの有効期限が切れており、DB に対してクエリを実行するリクエストがありません。この要求は、クエリを作成するために前進します。
ただし、同じ名前のストアド プロシージャを対象とするデータベース クエリは、キューに入れる必要があります (要件)。
したがって、これらのクエリをキューに入れ、同時にではなく連続して実行するように設計されたこのキュー クラスを作成しました。これらのキュー クラスは必要に応じて作成され、シングルトン クラスのリストに格納されます。要求がパート (3) に移動すると、そのストアド プロシージャ名に一致するキュー クラスを見つけ、そのキュー クラスに要求を送信します。次に、DB からデータが返されるまで待機して、HTML 要求を処理できるようにします。
残念ながら、このコードを配置して数時間後、サーバー プロセスは 100% に達します。
マルチスレッドコーディングは私の専門ではないため、改善する最善の方法はわかりません。
キュー クラスのコードは次のようになります。
public ReportTable GetReportTable(ReportQuery query)
{
lock (_queue)
{
_queue.Enqueue(query);
Monitor.Pulse(_queue);
}
lock (_queue)
{
var firstQueryInQueue = _queue.Peek();
while (_inUse || firstQueryInQueue == null || firstQueryInQueue.GetHashCode() != query.GetHashCode())
{
Monitor.Pulse(_queue);
Monitor.Wait(_queue);
}
_inUse = true;
firstQueryInQueue = _queue.Dequeue();
var table = firstQueryInQueue.GetNewReportTable();
_inUse = false;
Monitor.Pulse(_queue);
return table;
}
}