2010-12-15 14 views
3

Dies ist meine Funktion zum Aufzählen von Prozessen in Windows-Box und Berechnung der prozentualen CPU-Auslastung für jeden Prozess, aber die Ergebnisse sind nicht korrekt.Falsche berechnete CPU-Auslastung mit C# und WMI

CPU-Auslastung addiert sich nicht zu 100%, sondern eher zu 120% oder 130% und ich weiß nicht, was ich falsch mache. Es scheint, als ob es die richtige CPU-Auslastung für verschiedene Apps wie Firefox, VS2010, Office, .. berechnet aber Probleme mit System Idle Process hat.

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; 
} 

EDIT:

Ich fand, dass meine Funktion ist alles falsch.

Ich beginne ein Kopfgeld für die beste Arbeitslösung. Lösung muss für lokales und entferntes System funktionieren und sollte schnell sein.

+0

Wenn Sie nicht gezwungen sind, WMI zu verwenden, gibt es eine andere Art und Weise perf Zähler mit: http://stackoverflow.com/questions/278071/how-to-get-the-cpu-usage-in-c –

+1

Ist es möglich, dass sich die Werte zwischen Iterationen Ihrer Loops ändern? Das heißt, ein Element hat Prozessorzeit an einem Punkt der Schleife und dann bekommt ein anderer Zeit während der nächsten Iteration? Nur ein Gedanke ... –

+0

Ich stimme Mark zu - Sie sollten einen Schnappschuss der Leistungsindikatoren machen (vorzugsweise parallel, wenn Sie können, um Ihre Chance zu maximieren, sie alle zur gleichen Zeit zu bekommen) Dann machen Sie Mathe auf sie. Sie sind in einem Zustand der Flucht. –

Antwort

2

Hier ist ein C# -Code mit Leistungsindikatoren:

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()); 
    } 
} 

es von hier inspiriert ist: http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx Man kann nicht wirklich schneller sein als dies der Grund, warum in dem Artikel erklärt. Im Grunde müssen Sie den Wert zweimal lesen, um den richtigen Wert zu erhalten. Sie müssen also zwischen den Samples warten.

Je nachdem, was Sie zum Beispiel tun möchten, nehmen Sie an, Sie möchten einen "remote task manager" schreiben. Sie können dies in einer Hintergrundaufgabe (thread) codieren und die Werte regelmäßig aktualisieren. Der Benutzer wird die Verzögerung zwischen den Samples nicht wirklich sehen.

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); 
      } 
     } 
+0

Haben Sie meinen Code getestet? Funktioniert es? – fejesjoco

+0

+1, Wirklich besonders nützlich, wenn 'PerformanceCounter' kann schreckliche Leistung haben: https://StackOverflow.com/Questions/37819786/Whys-ist-Process-related-Data-User-Performance-Counters-Causing-so- viele – MaYaN

0

Hier ist ein C# Codeblock ist getestet und validiert und dank fejesjoco, benutzte ich seinen Code und machte den Test es zur Arbeit zu kommen.

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; 
    } 

}