Wie erhalte ich die CPU-Auslastung in C #?


203

Ich möchte die Gesamt-CPU-Auslastung für eine Anwendung in C # ermitteln. Ich habe viele Möglichkeiten gefunden, um die Eigenschaften von Prozessen zu untersuchen, aber ich möchte nur die CPU-Auslastung der Prozesse und die Gesamt-CPU, wie Sie sie im TaskManager erhalten.

Wie mache ich das?



36
Wie um alles in der Welt ist das nicht zum Thema? Lächerlich.
Peter Moore

Antworten:


205

Sie können die PerformanceCounter- Klasse von System.Diagnostics verwenden .

Initialisieren Sie wie folgt:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
ramCounter = new PerformanceCounter("Memory", "Available MBytes");

Konsumiere so:

public string getCurrentCpuUsage(){
            return cpuCounter.NextValue()+"%";
}

public string getAvailableRAM(){
            return ramCounter.NextValue()+"MB";
} 

80
Schön - aber die ursprüngliche Quelle scheint von hier zu sein: zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi

19
Nach dem, was ich entdeckt habe, musste ich cpuCounter.NextValue () zweimal verwenden und zwischen ihnen musste ich schlafen (500)
Angel.King.47

Matt hat recht. Sogar das Einschließen der Fehler, wie das Vergessen des Schlüsselworts "return".
Mark At Ramp51

8
Ja, es sieht aus wie eine Kopie von diesem Link, also wäre ein Link als Referenz für das Original ein schöner Stil gewesen. Andererseits ist es auch nett von CMS, die Antwort hier bereitzustellen, damit faule Entwickler nicht überall in Google suchen müssen, um dieselbe Antwort zu finden. : o)
BerggreenDK

13
Sie müssen .NextValue zweimal mit einem dazwischen liegenden System.Threading.Thread.Sleep-Aufruf aufrufen (1000 ms sollten ausreichen). Weitere Informationen dazu, warum dies erforderlich ist, finden Sie unter blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx . Die allgemeine Zusammenfassung lautet jedoch, dass Sie zwei Beispiele benötigen, um den Wert zu berechnen. und Sie müssen dem Betriebssystem eine Zeit geben, um beide zu erhalten.
Cleggy

62

Etwas mehr als erforderlich, aber ich verwende den zusätzlichen Timer-Code, um zu verfolgen und zu warnen, ob die CPU-Auslastung über einen längeren Zeitraum von 1 Minute oder länger 90% oder mehr beträgt.

public class Form1
{

    int totalHits = 0;

    public object getCPUCounter()
    {

        PerformanceCounter cpuCounter = new PerformanceCounter();
        cpuCounter.CategoryName = "Processor";
        cpuCounter.CounterName = "% Processor Time";
        cpuCounter.InstanceName = "_Total";

                     // will always start at 0
        dynamic firstValue = cpuCounter.NextValue();
        System.Threading.Thread.Sleep(1000);
                    // now matches task manager reading
        dynamic secondValue = cpuCounter.NextValue();

        return secondValue;

    }


    private void Timer1_Tick(Object sender, EventArgs e)
    {
        int cpuPercent = (int)getCPUCounter();
        if (cpuPercent >= 90)
        {
            totalHits = totalHits + 1;
            if (totalHits == 60)
            {
                Interaction.MsgBox("ALERT 90% usage for 1 minute");
                totalHits = 0;
            }                        
        }
        else
        {
            totalHits = 0;
        }
        Label1.Text = cpuPercent + " % CPU";
        //Label2.Text = getRAMCounter() + " RAM Free";
        Label3.Text = totalHits + " seconds over 20% usage";
    }
}

7
Wo ist der getRAMCounter ()?
Dieter B

1
cpuCounter.NextValuegibt a zurückfloat . Warum also einem zuweisen dynamic? Warum sollte man das dann dynamicals zurückgeben object? Warum sollte man dann versuchen, objectein intin der Zeile zuzuweisen int cpuPercent = getCPUCounter()? (Dieser Code wird nicht kompiliert.)
Wyck

21

Nachdem ich einige Zeit damit verbracht hatte, ein paar verschiedene Themen zu lesen, die ziemlich kompliziert erschienen, kam ich auf diese Idee. Ich brauchte es für einen 8-Kern-Computer, auf dem ich den SQL Server überwachen wollte. Für den folgenden Code habe ich dann "sqlservr" als appName übergeben.

private static void RunTest(string appName)
{
    bool done = false;
    PerformanceCounter total_cpu = new PerformanceCounter("Process", "% Processor Time", "_Total");
    PerformanceCounter process_cpu = new PerformanceCounter("Process", "% Processor Time", appName);
    while (!done)
    {
        float t = total_cpu.NextValue();
        float p = process_cpu.NextValue();
        Console.WriteLine(String.Format("_Total = {0}  App = {1} {2}%\n", t, p, p / t * 100));
        System.Threading.Thread.Sleep(1000);
    }
}

Es scheint den Prozentsatz der von SQL auf meinem 8-Core-Server verwendeten CPU korrekt zu messen.


total_cpu sollte PerformanceCounter ("Prozessor") sein, nicht PerformanceCounter ("Prozess"). Andernfalls erhalten Sie nur 100% * Anzahl der Kerne.
Steve Cook

3
Wo setzen Sie doneauf wahr? Sofern ich nichts übersehen habe, scheint dies eine Endlosschleife zu sein:while(!done){...}
Manfred

@Manfred Es ist in der Tat eine Endlosschleife
Jenny

16

Es ist in Ordnung, ich habe es verstanden! Danke für Ihre Hilfe!

Hier ist der Code dafür:

private void button1_Click(object sender, EventArgs e)
{
    selectedServer = "JS000943";
    listBox1.Items.Add(GetProcessorIdleTime(selectedServer).ToString());
}

private static int GetProcessorIdleTime(string selectedServer)
{
    try
    {
        var searcher = new
           ManagementObjectSearcher
             (@"\\"+ selectedServer +@"\root\CIMV2",
              "SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor WHERE Name=\"_Total\"");

        ManagementObjectCollection collection = searcher.Get();
        ManagementObject queryObj = collection.Cast<ManagementObject>().First();

        return Convert.ToInt32(queryObj["PercentIdleTime"]);
    }
    catch (ManagementException e)
    {
        MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
    }
    return -1;
}

Das Abrufen des Servernamens anstelle der Variablen selectedServer war besser. like this.string Computername = Environment.GetEnvironmentVariable ("Computername");
Dave


5

CMS hat es richtig gemacht, aber auch wenn Sie den Server-Explorer in Visual Studio verwenden und mit der Registerkarte Leistungsindikator herumspielen, können Sie herausfinden, wie Sie viele nützliche Metriken erhalten.


3

Dies scheint für mich zu funktionieren, ein Beispiel für das Warten, bis der Prozessor einen bestimmten Prozentsatz erreicht

var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
int usage = (int) cpuCounter.NextValue();
while (usage == 0 || usage > 80)
{
     Thread.Sleep(250);
     usage = (int)cpuCounter.NextValue();
}

Warum schläfst du, wenn die Nutzung 0 ist?
Watashi Shun

2

Diese Klasse fragt den Zähler automatisch alle 1 Sekunden ab und ist außerdem threadsicher:

public class ProcessorUsage
{
    const float sampleFrequencyMillis = 1000;

    protected object syncLock = new object();
    protected PerformanceCounter counter;
    protected float lastSample;
    protected DateTime lastSampleTime;

    /// <summary>
    /// 
    /// </summary>
    public ProcessorUsage()
    {
        this.counter = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public float GetCurrentValue()
    {
        if ((DateTime.UtcNow - lastSampleTime).TotalMilliseconds > sampleFrequencyMillis)
        {
            lock (syncLock)
            {
                if ((DateTime.UtcNow - lastSampleTime).TotalMilliseconds > sampleFrequencyMillis)
                {
                    lastSample = counter.NextValue();
                    lastSampleTime = DateTime.UtcNow;
                }
            }
        }

        return lastSample;
    }
}

System.DateTimeist eigentlich ein 8-Byte-Werttyp, was bedeutet, dass Zuweisungen zu einer DateTimeVariablen nicht atomar sind. Dieser Code ist auf 32-Bit-Plattformen nicht threadsicher.
Andrewjs

1

Ich mochte es nicht, alle PerformanceCounterLösungen im 1-Sekunden-Stall ergänzen zu müssen . Stattdessen habe ich mich für eine WMILösung entschieden. Der Grund für das 1-Sekunden-Warten / Stillstand besteht darin, dass der Messwert bei Verwendung von a genau istPerformanceCounter . Wenn Sie diese Methode jedoch häufig aufrufen und diese Informationen aktualisieren, würde ich raten, diese Verzögerung nicht ständig zu verursachen ... selbst wenn Sie daran denken, einen asynchronen Prozess durchzuführen, um sie abzurufen.

Ich habe mit dem Snippet von hier aus begonnen. Die CPU-Auslastung in WMI mithilfe von C # zurückgeben und eine vollständige Erklärung der Lösung in meinem Blog-Beitrag unten hinzugefügt:

Abrufen der CPU-Auslastung für alle Kerne in C # mithilfe von WMI


Bitte geben Sie die Antwort hier an, anstatt auf Ihr Blog zu verlinken.
Herman

@Herman - Ich habe nicht nur auf meinen Blog verlinkt; Ich gab zunächst eine Erklärung und stellte einen Link für eine ausführliche Antwort über den Beitrag hinaus bereit.
Atconway

Die Lösung in Ihrem Blog-Beitrag besteht aus 12 Codezeilen. Warum nehmen Sie das nicht in Ihre Antwort auf, außer zu versuchen, die Leute dazu zu bringen, Ihren Blog zu besuchen?
Herman

@Herman - Was ist das Problem beim Klicken auf den Link, da er eine ausführliche Erklärung enthält? Das ist die Idee der Warum-Teil-Ausarbeitung? Auch das ist 7 Jahre alt, nur zu sagen. Es ist schwer, mich an diesen genauen Beitrag zu erinnern, und ich war damals ein Neuling bei SO.
Atconway

Der Link könnte unterbrochen werden, und es ist viel einfacher, Antworten zu scannen, wenn der Kerninhalt inline ist. Es tut mir leid, dass ich in meiner anderen Antwort hart bin. Ich bin nicht hier, um es Ihnen schwer zu machen. :)
Herman

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.