我正在使用这个类作为一类测试的基类,这些测试启动一个进程并给它一些输入,并在给它更多输入之前等待它变为空闲.
public abstract class TestProcessLaunchingBase
{
protected PerformanceCounter PerfCounter { get; set; }
protected void WaitForProcessIdle()
{
while (true)
{
float oldValue = PerfCounter.NextValue();
Thread.Sleep(1000);
float nextValue = PerfCounter.NextValue();
if (nextValue == 0)
break;
}
}
protected void FindSpawnedProcessPerfCounter(int processId)
{
PerformanceCounterCategory cat = new PerformanceCounterCategory("Process");
string[] instances = cat.GetInstanceNames();
foreach (string instance in instances)
{
using (PerformanceCounter cnt = new PerformanceCounter("Process", "ID Process", instance, true))
{
int val = (int)cnt.RawValue;
if (val == processId)
{
PerfCounter = new PerformanceCounter("Process", "% Processor Time", instance);
break;
}
}
}
Assert.IsNotNull(PerfCounter, "Failed to perf counter");
}
}
Run Code Online (Sandbox Code Playgroud)
这些测试偶尔会失败,因为PerfCounter.NextValue()抛出
System.InvalidOperationException指定的类别中不存在实例'foobar#2'
似乎性能计数器的实例名称不是持久的.
如果有三个foobar进程,则它们可能具有实例名称
似乎pid 5332退出foobar#2变成了foobar#1.
问题:
这是记录在案的行为吗?你能坚持一个性能指标吗?你每次都要查一下吗?
或者,是否有一个性能计数器可以为名为foobar的所有进程提供处理器时间
我过去已经遇到过这个问题.ProcessName#InstanceNumber实例名称的模式显然是微软的糟糕选择,你知道为什么:)
所以基本上你有两个选择:
1)PerformanceCounter每次使用您的FindSpawnedProcessPerfCounter方法创建一个新实例.
2)按照KB281884中描述的步骤将模式更改ProcessName#InstanceNumber为ProcessName_ProcessID.
第一种解决方案的问题是每次都需要一些CPU时间来构建新实例.
第二种解决方案的问题是注册表修改也会影响所有也使用此性能计数器的程序.它需要在启动您的应用程序之前修改注册表.
您拥有的最后一个选项是根本不使用性能计数器.如果您只对这些ProcessorTime信息感兴趣,可以使用P/Invoke调用一些Kernel32函数来检索它.
编辑:
所述Process类还提供UserProcessorTime和PrivilegedProcessorTime(内核处理器时间) 的属性.两者都返回一个TimeSpan实例(=时间量),因此要检索一定百分比的处理器时间,您必须自己进行一些计算(包括刷新周期和处理器时间).
| 归档时间: |
|
| 查看次数: |
6127 次 |
| 最近记录: |