【发布时间】:2010-10-02 18:07:34
【问题描述】:
这是队列的设置:
- 队列是公开的并标记为事务性的。
- Web 服务负责将消息插入队列。
- Windows 服务正在侦听队列
鉴于此,我怎样才能只处理至少 20 分钟前的消息?
【问题讨论】:
-
请用简单的英文重新表述一下……很难理解你的问题是什么。
标签: c# .net msmq message-queue
这是队列的设置:
鉴于此,我怎样才能只处理至少 20 分钟前的消息?
【问题讨论】:
标签: c# .net msmq message-queue
鉴于队列是先进先出的,您必须假设队列中的所有消息的到达时间等于或晚于队列中第一条消息的时间。
你可以利用它来发挥你的优势。
基本上,您会在 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's comment,您不会在循环中处理此问题,而是只需从将在您指定的时间间隔触发的计时器上的事件处理程序调用 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分钟之后。
但是... 这两种情况都会导致问题,因为您只能查看第一条消息。因此,您必须在指定时间将消息消费到队列或其他结构中以进行处理。
【讨论】: