【发布时间】:2011-04-21 14:33:40
【问题描述】:
我想知道是否有一种方法可以使用 C# 以编程方式检查私有或公共 MSMQ 中有多少消息?我有代码可以检查队列是否为空或不使用包装在 try/catch 中的 peek 方法,但我从未见过任何有关显示队列中消息数量的信息。这对于监控队列是否正在备份非常有帮助。
【问题讨论】:
我想知道是否有一种方法可以使用 C# 以编程方式检查私有或公共 MSMQ 中有多少消息?我有代码可以检查队列是否为空或不使用包装在 try/catch 中的 peek 方法,但我从未见过任何有关显示队列中消息数量的信息。这对于监控队列是否正在备份非常有帮助。
【问题讨论】:
如果您想要一个私有队列的计数,您可以使用 WMI 执行此操作。 这是这个的代码:
// You can change this query to a more specific queue name or to get all queues
private const string WmiQuery = @"SELECT Name,MessagesinQueue FROM Win32_PerfRawdata_MSMQ_MSMQQueue WHERE Name LIKE 'private%myqueue'";
public int GetCount()
{
using (ManagementObjectSearcher wmiSearch = new ManagementObjectSearcher(WmiQuery))
{
ManagementObjectCollection wmiCollection = wmiSearch.Get();
foreach (ManagementBaseObject wmiObject in wmiCollection)
{
foreach (PropertyData wmiProperty in wmiObject.Properties)
{
if (wmiProperty.Name.Equals("MessagesinQueue", StringComparison.InvariantCultureIgnoreCase))
{
return int.Parse(wmiProperty.Value.ToString());
}
}
}
}
}
感谢Microsoft.Windows.Compatibility 包,这也适用于netcore/netstandard。
【讨论】:
由于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;
}
}
【讨论】:
队列中的消息计数可以使用以下代码找到。
MessageQueue messageQueue = new MessageQueue(".\\private$\\TestQueue");
var noOFMessages = messageQueue.GetAllMessages().LongCount();
【讨论】:
如果你需要一个快速的方法(我的机器每秒调用 25k),我推荐 Ayende 的基于 MQMgmtGetInfo() 和 PROPID_MGMT_QUEUE_MESSAGE_COUNT 的版本:
对于 C# 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 年开始的实现是否可以继续工作。
【讨论】:
没有可用的 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 方法似乎有问题,会引发异常【讨论】:
GetAllMessages获取静态快照
这对我有用。首先使用枚举器确保队列为空。
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
【讨论】:
//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();
这比您选择的要快。 您可以在“C:\Program Files (x86)\Microsoft SDKs\Windows”中获得 MSMQManagement 类引用,只需浏览此地址即可。更多详情,您可以访问http://msdn.microsoft.com/en-us/library/ms711378%28VS.85%29.aspx。
【讨论】:
您可以直接从 .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());
【讨论】:
我发现检索消息队列计数的最快方法是使用以下site 中的 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;
}
【讨论】:
我们使用 MSMQ 互操作。根据您的需要,您可以简化此操作:
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;
}
【讨论】: