在.NET中命名多实例性能计数器

Rog*_*mbe 11 .net performancecounter

如果有多个具有相同名称的实例,Windows中的大多数实例性能计数器似乎自动(?)最后都有#n.

例如:如果在Perfmon中查看该Process类别,您将看到:

...
dwm
explorer
explorer#1
...
Run Code Online (Sandbox Code Playgroud)

我有两个explorer.exe进程,所以第二个计数器的名称附加了#1.

当我尝试在.NET应用程序中执行此操作时:

  • 我可以创建类别,并注册实例(使用PerformanceCounterCategory.Create带有a 的实例CounterCreationDataCollection).
  • 我可以打开计数器进行写入和写入.

当我第二次打开计数器(在另一个过程中)时,它会打开同一个计数器.这意味着我有两个进程争夺计数器.

对文件PerformanceCounter.InstanceName,各国#未在允许的名称.

那么:我如何拥有实际多实例的多实例性能计数器?第二个(和后续的)实例#n附加到名称的位置?

那就是:我知道我可以将进程ID(例如)放在实例名称上.这有效,但有一个不幸的副作用,即重新启动进程会产生新的PID,并且Perfmon继续监视旧计数器.

更新:

我正在创建类别(和计数器),如下所示:

const string categoryName = "Test App";
const string counterName = "Number of kittens";
string instanceName =
    Path.GetFileNameWithoutExtension(
        Process.GetCurrentProcess().MainModule.FileName);

if (!PerformanceCounterCategory.Exists(categoryName))
{
    var counterCreationDataCollection = new CounterCreationDataCollection
        {
            new CounterCreationData(counterName, "",
                PerformanceCounterType.NumberOfItems32)
        };

    PerformanceCounterCategory.Create(categoryName, "",
        PerformanceCounterCategoryType.MultiInstance,
        counterCreationDataCollection);
}
Run Code Online (Sandbox Code Playgroud)

我打开柜台如下:

PerformanceCounter counter = new PerformanceCounter(
        categoryName, counterName, instanceName, readOnly: false);
Run Code Online (Sandbox Code Playgroud)

小智 4

我认为您的问题在于 .NET 在性能计数器方面更加宽松,并且实际上绕过了 PerfLib Win API。

使用本机 PerfLib API 时,您可以在设置期间注册类别 - 并使用句柄从进程创建实例。因此,对于本机 API,没有直接的方法来共享计数器实例。因此,当使用相同名称访问两个计数器实例时,它们实际上具有不同的句柄并适当地用#标记。

在 .NET 中,当您只需按名称寻址计数器和实例时,就会面临交叉更新的危险。由于 .NET 获取名称并枚举(使用 WMI)实例,即使它们正由不同的应用程序使用。

我认为添加 PID* 确实是最明智的解决方案 - 因为你们都有更好的跟踪能力并且不会发生碰撞。关于重新启动创建新计数器的问题,我没有看到问题;如果您允许该进程的多个实例在给定时间运行,您如何知道该实例是由于重新启动还是只是运行另一个可执行文件而创建的?

如果进程之间确实存在某种依赖性,则可以清理过时的计数器或采用其他逻辑。在 PerfMon 中,您可以观看“*”所有实例。

*或者如果您在流程背后有一些逻辑,这些逻辑在不考虑重新启动的情况下得以维护 - 例如某种任务 ID。