MSMQ Receive() method timeout

可紊 提交于 2019-12-05 00:30:04

Any particular reason you aren't using an event handler to listen to the queues? The System.Messaging library allows you to attach a handler to a queue instead of, if I understand what you are doing correctly, looping Receive every 10 seconds. Try something like this:

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

We are also using NServiceBus and had a similar problem inside our network.

Basically MSMQ is using UDP with two-phase commits. After a message is received it has to be acknowledged. Until it is acknowledged it can not be received on the client side as the receive transaction hasn't been finalized.

This was caused by different things in different times for us: - once this was due to the Distributed Transaction Coordinator unable to communicate between machines as firewall misconfiguration - another time we were using cloned virtual machines without sysprep which made internal MSMQ ids non-unique and made it receive a message to one machine and ack to another. Eventually MSMQ figures things out but it takes quite a while.

Hope this helps.

Try this

public Message Receive( TimeSpan timeout, Cursor cursor )

overloaded function.

To get a cursor for a MessageQueue, call the CreateCursor method for that queue.

A Cursor is used with such methods as Peek(TimeSpan, Cursor, PeekAction) and Receive(TimeSpan, Cursor) when you need to read messages that are not at the front of the queue. This includes reading messages synchronously or asynchronously. Cursors do not need to be used to read only the first message in a queue.

When reading messages within a transaction, Message Queuing does not roll back cursor movement if the transaction is aborted. For example, suppose there is a queue with two messages, A1 and A2. If you remove message A1 while in a transaction, Message Queuing moves the cursor to message A2. However, if the transaction is aborted for any reason, message A1 is inserted back into the queue but the cursor remains pointing at message A2.

To close the cursor, call Close.

If you want to use something completely synchronous and without event you can test this method

public object Receive(string path, int millisecondsTimeout)
{
    var mq = new System.Messaging.MessageQueue(path);
    var asyncResult = mq.BeginReceive();
    var handles = new System.Threading.WaitHandle[] { asyncResult.AsyncWaitHandle };
    var index = System.Threading.WaitHandle.WaitAny(handles, millisecondsTimeout);
    if (index == 258) // Timeout
    {
        mq.Close();
        return null;
    }
    var result = mq.EndReceive(asyncResult);
    return result;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!