Подтвердить что ты не робот

Есть ли способ проверить, сколько сообщений находится в очереди MSMQ?

Мне было интересно, есть ли способ программно проверить, сколько сообщений находится в частной или публичной MSMQ с помощью С#? У меня есть код, который проверяет, является ли очередь пустой или не использует метод peek, завернутый в try/catch, но я никогда не видел ничего о том, как показывать количество сообщений в очереди. Это было бы очень полезно для мониторинга при резервном копировании очереди.

4b9b3361

Ответ 1

Вы можете прочитать значение счетчика производительности для очереди непосредственно из .NET:

using System.Diagnostics;

// ...
var queueCounter = new PerformanceCounter(
    "MSMQ Queue", 
    "Messages in Queue", 
    @"machinename\private$\testqueue2");

Console.WriteLine( "Queue contains {0} messages", 
    queueCounter.NextValue().ToString());

Ответ 2

API недоступен, но вы можете использовать GetMessageEnumerator2, который достаточно быстр. Пример:

MessageQueue q = new MessageQueue(...);
int count = q.Count();

Реализация

public static class MsmqEx
{
    public static int Count(this MessageQueue queue)
    {
        int count = 0;
        var enumerator = queue.GetMessageEnumerator2();
        while (enumerator.MoveNext())
            count++;

        return count;
    }
}

Я также пробовал другие варианты, но у каждого есть некоторые недостатки

  • Счетчик производительности может вызывать исключение "Экземпляр..." не существует в указанной категории.
  • Чтение всех сообщений, а затем подсчет считается очень медленным, он также удаляет сообщения из очереди
  • Кажется, проблема с методом Peek, который генерирует исключение

Ответ 3

Если вам нужен быстрый метод (25k calls/second на моем ящике), я рекомендую версию Ayende на основе MQMgmtGetInfo() и PROPID_MGMT_QUEUE_MESSAGE_COUNT:

для С# https://github.com/hibernating-rhinos/rhino-esb/blob/master/Rhino.ServiceBus/Msmq/MsmqExtensions.cs

для VB https://gist.github.com/Lercher/5e1af6a2ba193b38be29

Происхождение, вероятно, было http://functionalflow.co.uk/blog/2008/08/27/counting-the-number-of-messages-in-a-message-queue-in/, но я не уверен, что эта реализация с 2008 года больше работает.

Ответ 4

Мы используем MSMQ Interop. В зависимости от ваших потребностей вы, возможно, упростите это:

    public int? CountQueue(MessageQueue queue, bool isPrivate)
    {
        int? Result = null;
        try
        {
            //MSMQ.MSMQManagement mgmt = new MSMQ.MSMQManagement();
            var mgmt = new MSMQ.MSMQManagementClass();
            try
            {
                String host = queue.MachineName;
                Object hostObject = (Object)host;
                String pathName = (isPrivate) ? queue.FormatName : null;
                Object pathNameObject = (Object)pathName;
                String formatName = (isPrivate) ? null : queue.Path;
                Object formatNameObject = (Object)formatName;
                mgmt.Init(ref hostObject, ref formatNameObject, ref pathNameObject);
                Result = mgmt.MessageCount;
            }
            finally
            {
                mgmt = null;
            }
        }
        catch (Exception exc)
        {
            if (!exc.Message.Equals("Exception from HRESULT: 0xC00E0004", StringComparison.InvariantCultureIgnoreCase))
            {
                if (log.IsErrorEnabled) { log.Error("Error in CountQueue(). Queue was [" + queue.MachineName + "\\" + queue.QueueName + "]", exc); }
            }
            Result = null;
        }
        return Result;

    }

Ответ 5

            //here queue is msmq queue which you have to find count.        
            int index = 0;
            MSMQManagement msmq = new MSMQManagement() ;   
            object machine = queue.MachineName;
            object path = null;
            object formate=queue.FormatName;
            msmq.Init(ref machine, ref path,ref formate);
            long count = msmq.MessageCount();

Это быстрее, чем вы выбрали. Вы получаете повторение класса MSMQManagement внутри "C:\Program Files (x86)\Microsoft SDK\Windows", просто просматривая этот адрес, вы его получите. для более подробной информации вы можете посетить http://msdn.microsoft.com/en-us/library/ms711378%28VS.85%29.aspx.

Ответ 6

Самый быстрый метод, который я нашел для получения очереди очереди сообщений, - это использовать метод peek из следующего сайта:

protected Message PeekWithoutTimeout(MessageQueue q, Cursor cursor, PeekAction action)
{
  Message ret = null;
  try
  {
     ret = q.Peek(new TimeSpan(1), cursor, action);
  }
  catch (MessageQueueException mqe)
  {
     if (!mqe.Message.ToLower().Contains("timeout"))
     {
        throw;
     }
  }
  return ret;
}

protected int GetMessageCount(MessageQueue q)
{
  int count = 0;
  Cursor cursor = q.CreateCursor();

  Message m = PeekWithoutTimeout(q, cursor, PeekAction.Current);
  {
     count = 1;
     while ((m = PeekWithoutTimeout(q, cursor, PeekAction.Next)) != null)
     {
        count++;
     }
  }
return count;
}

Ответ 7

Это сработало для меня. Использование Enumarator, чтобы убедиться, что очередь пуста первой.

   Dim qMsg As Message ' instance of the message to be picked 
        Dim privateQ As New MessageQueue(svrName & "\Private$\" & svrQName) 'variable svrnme = server name ; svrQName = Server Queue Name
        privateQ.Formatter = New XmlMessageFormatter(New Type() {GetType(String)}) 'Formating the message to be readable the body tyep
        Dim t As MessageEnumerator 'declared a enumarater to enable to count the queue
        t = privateQ.GetMessageEnumerator2() 'counts the queues 

        If t.MoveNext() = True Then 'check whether the queue is empty before reading message. otherwise it will wait forever 
            qMsg = privateQ.Receive
            Return qMsg.Body.ToString
        End If

Ответ 8

У меня возникли проблемы с получением принятого ответа из-за ошибки xxx does not exist in the specified Category. Ни одно из вышеперечисленных решений не работало для меня.

Однако просто указывать имя машины, как показано ниже, возможно, исправлено.

private long GetQueueCount()
{
    try
    {
        var queueCounter = new PerformanceCounter("MSMQ Queue", "Messages in Queue", @"machineName\private$\stream")
        {
            MachineName = "machineName"
        };

        return (long)queueCounter.NextValue();
    }
    catch (Exception e)
    {
        return 0;
    }
}

Ответ 9

Количество сообщений в очереди можно найти, используя следующий код.

MessageQueue messageQueue = new MessageQueue(".\\private$\\TestQueue");
var noOFMessages = messageQueue.GetAllMessages().LongCount();