MSMQ Receive()方法超时

mik*_*ike 12 .net c# timeout msmq

我刚才的原始问题是MSMQ Slow Queue Reading,但是我已经提出了这个问题,现在我觉得我知道这个问题更清楚了.

我的代码(实际上是我正在使用的开源库的一部分)看起来像这样:

queue.Receive(TimeSpan.FromSeconds(10), MessageQueueTransactionType.Automatic);
Run Code Online (Sandbox Code Playgroud)

哪个使用Messaging.MessageQueue.Receive函数和队列是MessageQueue.问题如下.

将使用指定的超时(10秒)调用上面的代码行.该Receive(...)函数是一个阻塞函数,并且应该阻塞,直到消息到达队列,此时它将返回.如果在超时之前没有收到任何消息,它将在超时时返回.如果在调用函数时消息在队列中,它将立即返回该消息.

然而,正在发生的Receive(...)是正在调用函数,看到队列中没有消息,因此等待新消息进入.当新消息进入时(超时之前),它没有检测到这条新消息并继续等待.最终会超时超时,此时代码会继续并Receive(...)再次调用,然后它会获取消息并对其进行处理.

现在,此问题仅在数天/周后发生.通过删除和重新创建队列,我可以再次正常工作.它发生在不同的计算机和不同的队列上.因此,似乎某些东西正在积累,直到它打破了该Receive(...)函数使用的触发/通知能力.

我检查了很多不同的东西,一切看起来都很正常,与正常工作的队列没什么不同.有足够的磁盘空间(13gig免费)和RAM(从我可以告诉的1GB大约350MB空闲).我检查了所有看起来与其他队列相同的注册表项,并且性能监视器没有显示任何异常.我也运行了TMQ工具,看不出任何明显的错误.

我在所有机器上都使用Windows XP,它们都安装了Service Pack 3.我没有向队列发送大量消息,最多每2秒发送一次,但通常不会那么频繁.这些消息也很小,远不及4MB的限制.

我刚刚注意到的唯一事情是C:\ WINDOWS\system32\msmq\storage中的p0000001.mq和r0000067.mq文件都是4,096KB,但是在其他计算机上它们的大小也是当前没有遇到问题的.问题不会立即发生在计算机上的每个队列中,因为我可以在计算机上重新创建1个问题队列,而其他队列仍然会遇到问题.

我对MSMQ不是很有经验,所以如果你发布可能要检查的东西,请解释如何检查它们或在哪里可以找到你所谈论的更多细节.

目前的情况是:

  • ComputerA - 4队列正常
  • ComputerB - 2个队列遇到问题,1个队列正常
  • ComputerC - 2队列遇到问题
  • ComputerD - 1队列正常
  • ComputerE - 2队列正常

所以我有大量的计算机/队列来比较和测试.

小智 8

您没有使用事件处理程序来侦听队列的任何特殊原因?System.Messaging库允许您将处理程序附加到队列,而不是,如果我理解您正在做什么,循环接收每10秒.尝试这样的事情:

class MSMQListener
{
    public void StartListening(string queuePath)
    {
        MessageQueue msQueue = new MessageQueue(queuePath);
        msQueue.ReceiveCompleted += QueueMessageReceived;
        msQueue.BeginReceive();
    }

    private void QueueMessageReceived(object source, ReceiveCompletedEventArgs args)
    {
        MessageQueue msQueue = (MessageQueue)source;

        //once a message is received, stop receiving
        Message msMessage = null;
        msMessage = msQueue.EndReceive(args.AsyncResult);

        //do something with the message

        //begin receiving again
        msQueue.BeginReceive();
    }
}
Run Code Online (Sandbox Code Playgroud)


Ram*_*sad 0

尝试这个

public Message Receive( TimeSpan 超时, Cursor 光标 )

重载函数。

要获取 MessageQueue 的游标,请调用该队列的 CreateCursor 方法。

当您需要读取不在队列前面的消息时,Cursor 与 Peek(TimeSpan, Cursor, PeekAction) 和 Receive(TimeSpan, Cursor) 等方法一起使用。这包括同步或异步读取消息。不需要使用游标来仅读取队列中的第一条消息。

读取事务内的消息时,如果事务中止,消息队列不会回滚游标移动。例如,假设有一个队列,其中包含两条消息 A1 和 A2。如果在事务中删除消息 A1,消息队列会将光标移动到消息 A2。但是,如果事务因任何原因中止,则消息 A1 会被插回到队列中,但光标仍指向消息 A2。

要关闭光标,请调用 Close。