Обработка сообщений из очереди с задержкой с использованием C # и VS.NET 2005 - PullRequest
0 голосов
/ 21 января 2009

Это настройка для очереди:

  1. Очередь общедоступна и помечена как транзакционная.
  2. За вставку сообщений в очередь отвечает веб-служба.
  3. Служба Windows ожидает в очереди

Учитывая это, как я могу обрабатывать только сообщения, возраст которых не менее 20 минут?

Ответы [ 3 ]

1 голос
/ 21 января 2009

Принимая во внимание, что очередь «первым пришел - первым вышел», вы должны предположить, что все сообщения, которые находятся в очереди, поступают в момент времени, равный или более поздний, чем время первого сообщения в очереди.

Вы можете использовать это в своих интересах.

По сути, вы вызываете метод Peek в своем экземпляре MessageQueue и смотрите на свойство 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);    
}

Затем вы можете запустить это в цикле, ожидая немного между (каждые пять секунд, десять, независимо от того, что вы считаете подходящим для частоты обработки):

// 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);
}

В идеале, основываясь на комментарии Чарльза Конвея , вы не будете обрабатывать это в цикле, а просто вызовете GetQueueMessage из обработчика событий по таймеру, который будет срабатывать в указанный вами интервал.

0 голосов
/ 21 января 2009
// 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);
   }

}
0 голосов
/ 21 января 2009

Предостережение: в какой момент вы определяете 20-минутный возраст?

Случай 1: Если определено на основании того, когда сообщение было сгенерировано и отправлено, вам придется использовать Message.SentTime. Затем вы можете использовать Peek для просмотра сообщения и отложить обработку до достижения 20-минутного порога. Предполагается, что сообщения будут поступать в линейном порядке, что не гарантировано! (См. Ниже.)

Случай 2: Если определено на основе того, когда сообщение поступает в очередь, обратите внимание на время Message.ArrivedTime (процесс IE «прослушивает» очередь сообщений) и потребляет 20 минут спустя ,

Но ... В обоих случаях возникает проблема, так как вы можете посмотреть только первое сообщение. Таким образом, вам нужно будет отправить сообщение в очередь или другую структуру для обработки в назначенное время.

...