C#を使用してプライベートまたはパブリックMSMQにあるメッセージの数をプログラムで確認する方法があるかどうか疑問に思っていましたか?キューが空であるか、try/catchにラップされたpeekメソッドを使用していないかをチェックするコードがありますが、キュー内のメッセージ数を表示することについては見たことがありません。これは、キューがバックアップされているかどうかを監視するのに非常に役立ちます。
キューのパフォーマンスカウンター値は、.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());
利用可能な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
メソッドに問題があるようです高速な方法(ボックスで毎秒25k回の呼び出し)が必要な場合は、MQMgmtGetInfo()およびPROPID_MGMT_QUEUE_MESSAGE_COUNTに基づくAyendeのバージョンをお勧めします。
c#の場合 https://github.com/hibernating-rhinos/rhino-esb/blob/master/Rhino.ServiceBus/Msmq/MsmqExtensions.cs
for 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年以降のこの実装が機能することを確信していません。
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;
}
//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 にアクセスしてください。
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;
}
}
メッセージキューカウントを取得するために見つけた最速の方法は、次の 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;
}
これは私のために働いた。エニュマレーターを使用して、最初にキューが空であることを確認します。
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