これは、キューのセットアップです。
- キューはパブリックであり、トランザクションとしてマークされています。
- Web サービスは、メッセージをキューに挿入する役割を果たします。
- Windows サービスがキューでリッスンしています
では、20 分以上経過したメッセージのみを処理するにはどうすればよいでしょうか?
これは、キューのセットアップです。
では、20 分以上経過したメッセージのみを処理するにはどうすればよいでしょうか?
キューが先入れ先出しであるとすると、キュー内のすべてのメッセージは、キュー内の最初のメッセージと同じかそれ以降の時間に到着すると想定する必要があります。
あなたはそれをあなたの利益のために使うことができます。
基本的に、MessageQueueインスタンスでPeekメソッドを呼び出し、ArrivedTimeプロパティを確認します。現在から到着時刻までの時間が20分を超える場合は、それを処理します。それ以外の場合は、(次にキューでメッセージを処理するまで)待機し続けます。
次に例を示します。
static Message GetQueueMessage(MessageQueue queue)
{
// Store the current time.
DateTime now = DateTime.Now;
// Get the message on top of the queue.
Message message = queue.Peek();
// If the current time is greater than or equal to 20 minutes, then process it,
// otherwise, get out and return false. Generate 20 minutes first.
// You can refactor this to have it passed in.
TimeSpan delay = TimeSpan.FromMinutes(20);
// If the delay is greater than the arrived time and now, then get out.
if (delay > (now - message.ArrivedTime))
{
// Return null.
return null;
}
// Pop the message from the queue to remove it.
return queue.ReceiveById(message.Id);
}
次に、これをループで実行し、その間に少し待機します(5秒ごと、10秒ごと、処理の頻度に適していると思われるものは何でも)。
// Have some other reasonable check here.
do while (true)
{
// The message to process.
Message message = GetQueueMessage(queue);
// Continue to process while there is a message.
do while (message != null)
{
// Process the message.
// Get the next message.
message = GetQueueMessage(queue);
}
// Wait a little bit, five seconds for example.
Thread.Sleep(5000);
}
理想的には、 Charles Conwayのコメントに基づいて、これをループで処理するのではなく、指定された間隔で起動するタイマーのイベントハンドラーからGetQueueMessageを呼び出すだけです。
// Have some other reasonable check here.
do while (true)
{
...
}
ブール状態で「true」になるのはコードの臭いです...タイマーを使用して5秒ごとにウェイクアップすることを検討しましたか?
Timer timer = new Timer();
timer.Elapsed +=new ElapsedEventHandler(timer_Elapsed);
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
// The message to process.
Message message = GetQueueMessage(queue);
// Continue to process while there is a message.
do while (message != null)
{
// Process the message.
// Get the next message.
message = GetQueueMessage(queue);
}
}
これの警告は、どの時点で20分経過したと定義していますか?
ケース1:メッセージが生成および送信された日時に基づいて定義されている場合は、Message.SentTimeを使用する必要があります。次に、Peekを使用してメッセージを確認し、20分のしきい値に達するまで処理を遅らせることができます。 これは、メッセージが線形の順序で到着することを前提としていますが、これは保証されていません。(下記参照。)
ケース2:メッセージがキューに到着するタイミングに基づいて定義されている場合は、Message.ArrivedTime(IEプロセスがメッセージキューを「リッスン」している)の時間を記録し、20分後に消費します。
しかし...どちらの場合も、最初のメッセージしか覗くことができないため、問題が発生します。そのため、指定された時間に処理するために、メッセージをキューまたは他の構造に消費する必要があります。