这是我的功能,用于枚举Windows框中的进程并计算每个进程的CPU使用百分比,但结果不正确。
CPU使用率不是100%,而是120%或130%,我不知道我做错了什么。 它似乎计算了firefox,VS2010,office等各种应用程序的正确CPU使用率,但是系统空闲进程存在问题。
public List<ProcInfo> GetRunningProcesses()
{
List<ProcInfo> allProcesses = new List<ProcInfo>();
UInt64 currentProcessCpuTime = 0;
UInt64 allProcessCpuTime = 0;
SelectQuery wmiQuery = new SelectQuery("SELECT Name, Description, ProcessId, KernelModeTime, UserModeTime FROM Win32_Process");
ManagementObjectSearcher oSearcher = new ManagementObjectSearcher(connectionScope, wmiQuery);
ManagementObjectCollection moc = oSearcher.Get();
foreach (ManagementObject mo in moc)
{
allProcessCpuTime += (UInt64)mo["KernelModeTime"] + (UInt64)mo["UserModeTime"];
}
foreach (ManagementObject mo in moc)
{
currentProcessCpuTime = (UInt64)mo["KernelModeTime"] + (UInt64)mo["UserModeTime"];
allProcesses.Add(new ProcInfo((string)mo["Name"], (string)mo["Description"], (UInt32)mo["ProcessId"], (currentProcessCpuTime / (double)allProcessCpuTime * 100));
}
return allProcesses;
}
修改
我发现我的功能都错了。
我正在为最佳工作解决方案赢得奖励。解决方案需要适用于本地和远程系统,并且应该很快。
答案 0 :(得分:2)
以下是带有性能计数器的C#代码:
public static void DumpProcessesCpu(string machineName)
{
List<PerformanceCounter> counters = new List<PerformanceCounter>();
foreach (Process process in Process.GetProcesses(machineName))
{
PerformanceCounter processorTimeCounter = new PerformanceCounter(
"Process",
"% Processor Time",
process.ProcessName,
machineName);
processorTimeCounter.NextValue();
counters.Add(processorTimeCounter);
}
Thread.Sleep(1000); // 1 second wait, needed to get a sample
foreach (PerformanceCounter processorTimeCounter in counters)
{
Console.WriteLine("Process:{0} CPU% {1}",
processorTimeCounter.InstanceName,
processorTimeCounter.NextValue());
}
}
它的灵感来自于此:http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx 你不能真的比这更快,原因在文章中解释。基本上,您必须读取该值两次以使其正确,因此您需要在样本之间等待。
但是,根据您想要做的事情,例如,假设您要编写“远程任务管理器”,您可以在后台任务(线程)中对所有这些进行编码,并定期更新值以便最终用户我不会真正看到样品之间的延迟。
答案 1 :(得分:1)
var mos = new ManagementObjectSearcher("SELECT * FROM Win32_PerfRawData_PerfProc_Process");
var run1 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => (ulong)mo.Properties["PercentProcessorTime"].Value);
Thread.Sleep(570); // can be an arbitrary number
var run2 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => (ulong)mo.Properties["PercentProcessorTime"].Value);
var total = run2["_Total"] - run1["_Total"];
foreach (var kvp in run1)
{
var proc = kvp.Key;
var p1 = kvp.Value;
if (run2.ContainsKey(proc))
{
var p2 = run2[proc];
Console.WriteLine("{0}: {1:P}", proc, (double)(p2 - p1) / total);
}
}
答案 2 :(得分:0)
这是一个经过测试和验证的C#代码块,感谢fejesjoco,我使用了他的代码并进行了测试以使其工作。
public class CPUUtilizationTests
{
[Test]
public void TestPercentProcessorTime()
{
Assert.That(PercentProcessorTime("Idle"), Is.Not.GreaterThan(100.0));
}
public float PercentProcessorTime(string processName)
{
var mos = new ManagementObjectSearcher("SELECT * FROM Win32_PerfRawData_PerfProc_Process");
var run1 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => mo);
System.Threading.Thread.Sleep(1000); // can be an arbitrary number
var run2 = mos.Get().Cast<ManagementObject>().ToDictionary(mo => mo.Properties["Name"].Value, mo => mo);
if (!run2.ContainsKey(processName)) throw new Exception(string.Format("Process not found: {0}", processName));
string percentageProcessorTime = "PercentProcessorTime";
string total = "_Total";
ulong percentageDiff = (ulong)run2[processName][percentageProcessorTime] - (ulong)run1[processName][percentageProcessorTime];
ulong totalDiff = (ulong)run2[total][percentageProcessorTime] - (ulong)run1[total][percentageProcessorTime];
return ((float)percentageDiff / (float)totalDiff)*100.0f;
}
}