0

这是队列的设置:

  1. 队列是公共的并标记为事务性的。
  2. Web 服务负责将消息插入队列。
  3. Windows 服务正在侦听队列

鉴于此,我怎样才能只处理至少 20 分钟前的消息?

4

3 回答 3

1

鉴于队列是先进先出的,您必须假设队列中的所有消息的到达时间等于或晚于队列中第一条消息的时间。

你可以利用它来发挥你的优势。

基本上,您会在 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,该事件处理程序将在您指定的时间间隔内触发。

于 2009-01-21T19:21:08.010 回答
1
// Have some other reasonable check here.
do while (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);
   }

}
于 2009-01-21T19:28:29.727 回答
0

需要注意的是,您在什么时候定义 20 分钟大?

案例 1:如果根据生成和发送消息的时间进行定义,那么您将不得不使用 Message.SentTime。然后,您可以使用 Peek 查看消息,并延迟处理,直到达到 20 分钟的阈值。 这假设消息将以线性顺序到达,但不能保证!(见下文。)

情况2:如果根据消息到达队列的时间来定义,注意Message.ArrivedTime的时间(IE进程正在“监听”消息队列)并在20分钟后消费。

但是...这两种情况都会导致问题,因为您只能查看第一条消息。因此,您必须在指定时间将消息消费到队列或其他结构中以进行处理。

于 2009-01-21T19:20:17.077 回答