Come ottenere l'utilizzo della CPU in C #?


Risposte:


205

È possibile utilizzare la classe PerformanceCounter da System.Diagnostics .

Inizializza in questo modo:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

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

Consuma così:

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

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

80
Bello - ma la fonte originale sembra essere da qui: zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi,

19
Da quello che ho scoperto ho dovuto usare cpuCounter.NextValue () due volte e tra loro ho dovuto dormire (500)
Angel.King.47

Matt ha ragione. Anche includendo i bug, come dimenticare la parola chiave "return".
Mark At Ramp51

8
sì, sembra una copia di quel link, quindi un link per riferimento all'originale sarebbe stato bello stile. D'altra parte, è anche carino da parte di CMS fornire la risposta qui, quindi gli sviluppatori pigri non devono cercare su Google per trovare la stessa risposta. : o)
BerggreenDK

13
Dovrai chiamare .NextValue due volte, con una chiamata System.Threading.Thread.Sleep in mezzo (1000ms dovrebbero essere sufficienti). Vedere blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx per ulteriori informazioni sul perché ciò è necessario, ma il riepilogo di alto livello è che è necessario disporre di due campioni per calcolare il valore, ed è necessario concedere al sistema operativo il tempo necessario per ottenere entrambi.
Cleggy

63

Un po 'più di quanto fosse necessario, ma uso il codice timer aggiuntivo per tenere traccia e avvisare se l'utilizzo della CPU è del 90% o superiore per un periodo prolungato di 1 minuto o più.

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
Dov'è getRAMCounter ()?
Dieter B,

1
cpuCounter.NextValuerestituisce afloat . Quindi perché assegnarlo a dynamic? Allora perché restituirlo dynamiccome object? Allora perché provare ad assegnare un objecta un intnella linea int cpuPercent = getCPUCounter()? (Quel codice non verrà compilato.)
Wyck,

21

Dopo aver trascorso un po 'di tempo a leggere un paio di thread diversi che sembravano piuttosto complicati, mi sono inventato questo. Ne avevo bisogno per una macchina a 8 core in cui volevo monitorare il server SQL. Per il codice seguente ho passato "sqlservr" come appName.

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

Sembra misurare correttamente la% di CPU utilizzata da SQL sul mio server 8 core.


total_cpu dovrebbe essere PerformanceCounter ("Processor"), non PerformanceCounter ("Process") .. altrimenti otterrai solo il 100% * numero di core.
Steve Cook,

3
Dove imposti donesu vero? A meno che non abbia trascurato qualcosa, questo sembra essere un ciclo infinito:while(!done){...}
Manfred,

@Manfred È davvero un ciclo infinito
Jenny

16

Va bene, ho capito! Grazie per l'aiuto!

Ecco il codice per farlo:

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

Aggiungi ottenere il nome del server invece della variabile selezionata Il server era migliore. like this.string nomecomputer = Environment.GetEnvironmentVariable ("nomecomputer");
Dave


5

CMS ha ragione, ma anche se si utilizza Esplora server in Visual Studio e si gioca con la scheda Contatore delle prestazioni, è possibile capire come ottenere molte metriche utili.


3

Questo sembra funzionare per me, un esempio per aspettare fino a quando il processore raggiunge una certa percentuale

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

perché dormi quando l'utilizzo è 0?
WatashiSHUN,

2

Questa classe esegue automaticamente il polling del contatore ogni 1 secondi ed è anche thread-safe:

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.DateTimeè in realtà un tipo di valore a 8 byte, il che significa che le assegnazioni a una DateTimevariabile non sono atomiche. Questo codice non è thread-safe su piattaforme a 32 bit.
andrewjs,

1

Non mi è piaciuto dover aggiungere lo stallo di 1 secondo a tutte le PerformanceCountersoluzioni. Invece ho scelto di usare una WMIsoluzione. Il motivo per cui esiste 1 secondo di attesa / stallo è quello di consentire la lettura accurata quando si utilizza a PerformanceCounter. Tuttavia, se chiami spesso questo metodo e aggiorni queste informazioni, ti consiglio di non dover sostenere costantemente questo ritardo ... anche se stai pensando di fare un processo asincrono per ottenerlo.

Ho iniziato con lo snippet da qui Restituendo l'utilizzo della CPU in WMI utilizzando C # e ho aggiunto una spiegazione completa della soluzione sul mio post di blog di seguito:

Ottieni l'utilizzo della CPU in tutti i core in C # usando WMI


Includi qui la risposta invece di collegarti al tuo blog.
Herman

@Herman - Non ho solo link al mio blog; Ho dato una spiegazione prima e ho provveduto a fornire un link per una risposta approfondita oltre il post qui.
atconway,

la soluzione nel tuo post sul blog è come 12 righe di codice. Perché non includerlo nella tua risposta oltre a cercare di far visitare il tuo blog alle persone?
Herman

@Herman - Qual è il problema facendo clic sul collegamento in quanto contiene una spiegazione approfondita; questa è l'idea dell'elaborazione della porzione "perché"? Anche questo ha 7 anni, sto solo dicendo. Difficile ricordare questo post esatto e io ero un newb su SO allora.
atconway,

il collegamento potrebbe interrompersi ed è molto più semplice scansionare le risposte quando il contenuto principale è in linea. Scusami per essere stato duro nell'altra mia risposta, non sono qui per darti problemi. :)
Herman,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.