2014-06-09 7 views
9

Dies ist, was in form1 im tut:Warum erhalte ich immer eine CPU-Auslastung von 0%?

void PopulateApplications() 
{ 
    DoubleBufferedd(dataGridView1, true); 

    int rcount = dataGridView1.Rows.Count; 
    int rcurIndex = 0; 

    foreach (Process p in Process.GetProcesses()) 
    { 
     try 
     { 
      if (File.Exists(p.MainModule.FileName)) 
      { 
       memoryUsage = Core.getallmemoryusage(p.ProcessName); 
       Core.getcpu(p.ProcessName); 
       cpuusage = Core.processes; 

       var icon = Icon.ExtractAssociatedIcon(p.MainModule.FileName); 
       Image ima = icon.ToBitmap(); 
       ima = resizeImage(ima, new Size(25, 25)); 
       ima = (Image)(new Bitmap(ima, new Size(25, 25))); 
       String status = p.Responding ? "Running" : "Not Responding"; 

       if (rcurIndex < rcount - 1) 
       { 
        var currentRow = dataGridView1.Rows[rcurIndex]; 
        currentRow.Cells[0].Value = ima; 
        currentRow.Cells[1].Value = p.ProcessName; 
        currentRow.Cells[2].Value = cpuusage; 
        currentRow.Cells[3].Value = memoryUsage; 
        currentRow.Cells[4].Value = status; 
       } 
       else 
       { 
        dataGridView1.Rows.Add(ima, p.ProcessName,cpuusage,memoryUsage, status);//false, ima, p.ProcessName, status); 
       } 

       rcurIndex++; 
      } 
     } 
     catch (Exception e) 
     { 
      string t = "error"; 
     } 
    } 

    if (rcurIndex < rcount - 1) 
    { 
     for (int i = rcurIndex; i < rcount - 1; i++) 
     { 
      dataGridView1.Rows.RemoveAt(rcurIndex); 
     } 
    } 
} 

Nun wird das Verfahren in form1 PopulateApplications ich es von einem Timer-Tick-Ereignis alle 5 Sekunden anrufen. Dann Schleife ich jedes Mal über die Prozesse und bekomme die Speicherauslastung und CPU-Auslastung. Dies sind die Methoden von Speicher und CPU in der Klasse Core.

Mit der Speichermethode gibt es keine Probleme. Arbeiten gut und schnell.

public static string getallmemoryusage(string processName) 
{ 
    var counter = new PerformanceCounter("Process", "Working Set - Private", processName); 
    privateMemeory = (counter.NextValue()/1024/1024).ToString(); 
    //string.Format("Private memory: {0}k", counter.NextValue()/1024/1024); 
    return privateMemeory;   
} 

Das Problem ist mit der getcpu Methode. Ich muss es alle 1000ms einige Male schlafen lassen, um die CPU-Auslastung zu erhalten. Wenn ich für diese Methode einen Haltepunkt verwende, erhalte ich am Ende den Wert. Das Problem ist, wenn ich die Methode in form1 alle 5 Sekunden anrufe und diese getcpu alle 5 Sekunden aufruft und diese Threads schlafen machen es sehr langsam. Wenn ich die Threads auf 10ms setzen will, wird es schneller, aber dann bekomme ich bei den meisten Prozessen 0% oder 100%.

public static string getcpu(string name) 
{ 
    var cpuload = new PerformanceCounter("Processor", "% Processor Time", "_Total"); 

    processes = Convert.ToInt32(cpuload.NextValue()) + "%"; 
    System.Threading.Thread.Sleep(1000); 

    processes = cpuload.NextValue() + "%"; 
    System.Threading.Thread.Sleep(1000); 

    processes = cpuload.NextValue() + "%"; 
    System.Threading.Thread.Sleep(1000); 

    processes = cpuload.NextValue() + "%"; 
    System.Threading.Thread.Sleep(1000); 

    processes = cpuload.NextValue() + "%"; 
    System.Threading.Thread.Sleep(1000); 

    return processes; 
} 
+0

Rotum rechts i meine Frage geändert mit aktualisierten getcpu Methode mit dem Namen Variable und im nicht itertiing auf alle Prozesse wieder nur in form1 einmal. Trotzdem bekomme ich bei jedem Prozess 0%. Zum Beispiel in der Testliste sehe ich 1 Index und: chorme CPU0% und das gleiche für jeden Prozess. – user3681442

+0

In der Getcpu-Methode bekomme ich keine Ausnahme, die ich hinzugefügt habe, versuchen und fangen jetzt keine Ausnahmen. Aber in form1 gibt es manchmal Exceptions für einige Prozesse, die verweigert werden, aber das sind Systemprozesse, also macht es mir nichts aus, dass sie Zugriff verweigert bekommen. – user3681442

+0

Ich habe gerade meine Frage aktualisiert, die zeigt, dass der Speicherverbrauch keine Probleme verursacht. Trotzdem funktioniert die CPU-Nutzung nicht. – user3681442

Antwort

6

Wenn % Processor Time Messung der Thread.Sleep(1000) erforderlich, da der .NextValue() Aufruf bestimmt die Zeit, wurde der Prozessor seit dem letzten Aufruf von .NextValue() verwendet. Weitere Informationen zu dieser Berechnung finden Sie unter http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx.

Ein paar Vorschläge:

1) Da Sie im Namen eines Prozesses sind vorbei, ich nehme an, Sie die Prozessorzeit eines einzelnen Prozesses messen möchten. Da Sie diesen Parameter jedoch nicht innerhalb Ihrer Methode verwenden, messen Sie stattdessen die durchschnittliche Systemprozessorzeit.

Also, wenn Sie die Leistung für einen einzigen Prozess messen wollen, könnten Sie so etwas wie verwenden:

public static double GetCpuUsage(Process process) 
{ 
    PerformanceCounter cpuCounter = new PerformanceCounter(); 

    cpuCounter.CategoryName = "Process"; 
    cpuCounter.InstanceName = process.ProcessName; 
    cpuCounter.CounterName = "% Processor Time"; 

    // The first call will always return 0 
    cpuCounter.NextValue(); 
    // That's why we need to sleep 1 second 
    Thread.Sleep(1000); 
    // The second call determines, the % of time that the monitored process uses on 
    // % User time for a single processor. 
    // So the limit is 100% * the number of processors you have. 
    double processorUsagePercent = cpuCounter.NextValue(); 

    // Hence we need to divide by the number of processors to get the average CPU usage of one process during the time measured 
    return processorUsagePercent/Environment.ProcessorCount; 
} 

Bitte beachten Sie den Unterschied zwischen "Processor" und "Process" für den Zähler Kategorie.

2) Warum rufen Sie mehrmals hintereinander .NextValue() an und geben nur den letzten Wert zurück? Das macht deine Methode so langsam. Die beiden im obigen Beispiel gezeigten Berechnungen sind ausreichend.

3) Wenn Sie mehrere Prozesse überwachen möchten, müssen Sie keine Sekunde zwischen jedem Aufruf an .NextValue() warten. Sie müssen lediglich sicherstellen, dass seit dem letzten Aufruf von .NextValue() für einen bestimmten Zähler mindestens eine Sekunde verstrichen ist. Also für mehrere Prozesse könnten Sie eine Methode wie die haben:

public static Dictionary<Process, double> GetCpuUsages(Process[] processes) 
{ 
    // One performance counter is required per process 
    PerformanceCounter[] counters = new PerformanceCounter[processes.Length]; 

    // Instantiate a new counter per process 
    for(int i = 0; i < processes.Length; i++) 
    { 
     PerformanceCounter processorTimeCounter = new PerformanceCounter(
      "Process", 
      "% Processor Time", 
      processes[i].ProcessName); 
     // Call NextValue once to have a reference value 
     processorTimeCounter.NextValue(); 
     // Add it to the array 
     counters[i] = processorTimeCounter; 
    } 

    // Sleep one second to have accurate measurement 
    Thread.Sleep(1000); 
    // Here we store the processes along with their measurement in a dictionary 
    Dictionary<Process, double> cpuUsageDictionary = new Dictionary<Process, double>(); 

    for (int i = 0; i < counters.Length; i++) 
    { 
     // Determine CPU usage and divide by the number of cores 
     double cpuUsage = counters[i].NextValue()/Environment.ProcessorCount; 
     // And now we add one key/value pair per process along with its cpu time measurement 
     cpuUsageDictionary.Add(processes[i], cpuUsage); 
    } 

    return cpuUsageDictionary; 
} 
Verwandte Themen