Мне было интересно, есть ли способ программно проверить, сколько сообщений находится в частной или публичной MSMQ с помощью С#? У меня есть код, который проверяет, является ли очередь пустой или не использует метод peek, завернутый в try/catch, но я никогда не видел ничего о том, как показывать количество сообщений в очереди. Это было бы очень полезно для мониторинга при резервном копировании очереди.
Есть ли способ проверить, сколько сообщений находится в очереди MSMQ?
Ответ 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();