如何以编程方式检查NServiceBus是否已完成处理所有消息

Nat*_*ber 5 c# msmq nservicebus

作为自动启动/停止某些NServiceBus服务的努力的一部分,我想知道服务何时完成处理其输入队列中的所有消息.

问题是,当NServiceBus服务正在运行时,我的C#代码报告的消息少于实际消息.所以当剩下一条消息时,它认为队列是空的.如果服务停止,它将报告"正确"的消息数.这很令人困惑,因为当我使用"计算机管理"应用程序中的"专用队列"视图自行检查队列时,它会显示"正确"的数字.

我正在使用以下C#代码的变体来查找消息计数:

var queue = new MessageQueue(path);
return queue.GetAllMessages().Length;
Run Code Online (Sandbox Code Playgroud)

我知道当有很多消息时,这会表现得非常糟糕.我正在检查的队列一次只能有一些消息.

我查看了 其他 相关 问题,但没有找到我需要的帮助.

任何见解或建议将不胜感激!

更新:我应该提到此服务是在分发服务器后面,在尝试关闭此服务之前,该服务器已关闭.所以我有信心不会将新消息添加到服务的输入队列中.

Nat*_*ber 1

WMI 就是答案!这是代码的第一遍。毫无疑问,它还可以改进。

public int GetMessageCount(string queuePath)
{
    const string query = "select * from Win32_PerfRawData_MSMQ_MSMQQueue";
    var query = new WqlObjectQuery(query);
    var searcher = new ManagementObjectSearcher(query);
    var queues = searcher.Get();

    foreach (ManagementObject queue in queues)
    {
        var name = queue["Name"].ToString();
        if (AreTheSameQueue(queuePath, name))
        {
            // Depending on the machine (32/64-bit), this value is a different type.
            // Casting directly to UInt64 or UInt32 only works on the relative CPU architecture.
            // To work around this run-time unknown, convert to string and then parse to int.
            var countAsString = queue["MessagesInQueue"].ToString();
            var messageCount = int.Parse(countAsString);
            return messageCount;
        }
    }

    return 0;
}

private static bool AreTheSameQueue(string path1, string path2)
{
    // Tests whether two queue paths are equivalent, accounting for differences
    // in case and length (if one path was truncated, for example by WMI).

    string sanitizedPath1 = Sanitize(path1);
    string sanitizedPath2 = Sanitize(path2);

    if (sanitizedPath1.Length > sanitizedPath2.Length)
    {
        return sanitizedPath1.StartsWith(sanitizedPath2);
    }

    if (sanitizedPath1.Length < sanitizedPath2.Length)
    {
        return sanitizedPath2.StartsWith(sanitizedPath1);
    }

    return sanitizedPath1 == sanitizedPath2;
}

private static string Sanitize(string queueName)
{
    var machineName = Environment.MachineName.ToLowerInvariant();
    return queueName.ToLowerInvariant().Replace(machineName, ".");
}
Run Code Online (Sandbox Code Playgroud)