异常:Instance '在指定的类别中不存在
本文关键字:不存在 Instance 异常 | 更新日期: 2023-09-27 17:54:20
当我像这样创建和使用性能计数器时:
private readonly PerformanceCounter _cpuPerformanceCounter;
public ProcessViewModel(Process process)
{
_cpuPerformanceCounter = new PerformanceCounter("Process", "% Processor Time", process.ProcessName, true);
}
public void Update()
{
CPU = (int)_cpuPerformanceCounter.NextValue() / Environment.ProcessorCount; // Exception
}
…我得到一个异常实例'实例的名称'不存在于指定的类别,不明白为什么。
注:代码
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<settings>
<performanceCounters enabled="true"/>
</settings>
</system.net>
</configuration>
…
加上之前的帖子,我看到过进程被格式化为
private string ObtainProcessName()
{
string baseProcessName;
string processName = null;
int processId;
bool notFound = true;
int processOptionsChecked = 0;
int maxNrOfParallelProcesses = 3 + 1;
try
{
baseProcessName = Process.GetCurrentProcess().ProcessName;
}
catch (Exception exception)
{
return null;
}
try
{
processId = Process.GetCurrentProcess().Id;
}
catch (Exception exception)
{
return null;
}
while (notFound)
{
processName = baseProcessName;
if (processOptionsChecked > maxNrOfParallelProcesses)
{
break;
}
if (1 == processOptionsChecked)
{
processName = string.Format("{0}_{1}", baseProcessName, processId);
}
else if (processOptionsChecked > 1)
{
processName = string.Format("{0}#{1}", baseProcessName, processOptionsChecked - 1);
}
try
{
PerformanceCounter counter = new PerformanceCounter("Process", "ID Process", processName);
if (processId == (int)counter.NextValue())
{
notFound = !true;
}
}
catch (Exception)
{
}
processOptionsChecked++;
}
return processName;
}
我认为您的问题发生在有多个具有相同名称的进程时。PerfMon所做的就是在进程名后面加上#1,#2等。因此,这意味着MyApp.exe执行两次将导致此异常,当你试图读取"MyApp"的性能监视器。这里有一个解决这个问题的方法的链接:通过pid
以下是我对所有流程和多个流程实例的解决方案:
var processes = Process.GetProcesses().GroupBy(g => g.ProcessName);
List<Tuple<string, PerformanceCounter>> pcList = new List<Tuple<string, PerformanceCounter>>();
foreach (var pg in processes)
{
if (pg.First().ProcessName == "Idle")
continue;
if (pg.Count() == 1)
{
var process_cpu = new PerformanceCounter(
"Process",
"% Processor Time",
pg.First().ProcessName
);
process_cpu.NextValue();
pcList.Add(new Tuple<string, PerformanceCounter>(pg.First().ProcessName, process_cpu));
}
else
{
int id = 1;
foreach(var p in pg)
{
var process_cpu = new PerformanceCounter(
"Process",
"% Processor Time",
p.ProcessName + "#" + id
);
process_cpu.NextValue();
pcList.Add(new Tuple<string, PerformanceCounter>(p.ProcessName + "#" + id, process_cpu));
id++;
}
}
}
使用pid后缀的原始格式(注册表ProcessNameFormat = 1)似乎已经在。net 4.5 (msdn链接)更改为"processame_pid_rid"。因此,当前写入的可接受答案可能不再适用于这种情况。
这个解决方案应该仍然适用于较新的格式:
https://weblog.west-wind.com/posts/2014/Sep/27/Capturing-Performance-Counter-Data-for-a-Process-by-Process-Id然而,所有这些匹配的解决方案可能容易出现竞争条件,即在确定实例名之后,在分配新的PerformanceCounter()之前,由于进程退出(#9变为#8),实例名会发生变化。
对于MS来说,提供一个直接接受Pid(现在可能还有RuntimeId?)的PerformanceCounter构造函数会更有意义,因为实例名可以动态更改。
您可以查看此代码
Use > new PerformanceCounter("Processor Information", "% Processor Time", "_Total");
Instead of> new PerformanceCounter("Processor", "% Processor Time", "_Total");