¿Cómo obtener el uso de la CPU en C #?

204

Quiero obtener el uso total total de la CPU para una aplicación en C #. He encontrado muchas formas de profundizar en las propiedades de los procesos, pero solo quiero el uso de la CPU de los procesos y la CPU total como la que obtienes en el TaskManager.

¿Cómo puedo hacer eso?

Peter Mortensen
fuente
36
¿Cómo demonios está esto fuera de tema? Ridículo.
Peter Moore

Respuestas:

205

Puede usar la clase PerformanceCounter de System.Diagnostics .

Inicialice así:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

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

Consumir así:

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

public string getAvailableRAM(){
            return ramCounter.NextValue()+"MB";
} 
CMS
fuente
80
Agradable, pero la fuente original parece ser de aquí: zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi
19
Por lo que descubrí, tuve que usar cpuCounter.NextValue () dos veces y entre ellos tuve que dormir (500)
Angel.King.47
Matt tiene razón. Incluso incluyendo los errores, como olvidar la palabra clave "retorno".
Mark At Ramp51
8
Sí, parece una copia de ese enlace, por lo que un enlace para referencia del original habría sido un buen estilo. Por otro lado, también es bueno que CMS proporcione la respuesta aquí para que los desarrolladores perezosos no tengan que buscar en todo Google para encontrar la misma respuesta. : o)
BerggreenDK
13
Deberá llamar a .NextValue dos veces, con una llamada System.Threading.Thread.Sleep en el medio (1000ms debería ser suficiente). Consulte blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx para obtener más información sobre por qué esto es necesario, pero el resumen de alto nivel es que necesita dos muestras para calcular el valor, y necesita darle al sistema operativo un tiempo para obtener ambos.
Cleggy
63

Un poco más de lo requerido, pero utilizo el código del temporizador adicional para rastrear y alertar si el uso de la CPU es del 90% o más durante un período sostenido de 1 minuto o más.

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";
    }
}
Khalid Rahaman
fuente
77
¿Dónde está getRAMCounter ()?
Dieter B
1
cpuCounter.NextValuedevuelve afloat . Entonces, ¿por qué asignarlo a a dynamic? Entonces, ¿por qué devolver eso dynamiccomo un object? Entonces, ¿por qué tratar de asignar una objecta una inten la línea int cpuPercent = getCPUCounter()? (Ese código no se compilará).
Wyck
21

Después de pasar un tiempo leyendo un par de hilos diferentes que parecían bastante complicados, se me ocurrió esto. Lo necesitaba para una máquina de 8 núcleos donde quería monitorear el servidor SQL. Para el siguiente código, pasé "sqlservr" como 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);
    }
}

Parece medir correctamente el% de CPU que utiliza SQL en mi servidor de 8 núcleos.

MtnManChris
fuente
total_cpu debe ser PerformanceCounter ("Procesador"), no PerformanceCounter ("Proceso") ... de lo contrario, solo obtendrá el 100% * de núcleos.
Steve Cook
3
¿Dónde se establece doneen verdad? A menos que haya pasado por alto algo, este parece ser un ciclo sin fin:while(!done){...}
Manfred,
@Manfred De hecho, es un ciclo sin fin
Jenny
16

Está bien, lo tengo! ¡Gracias por tu ayuda!

Aquí está el código para hacerlo:

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;
}
besos y abrazos
fuente
Agregue obtener el nombre del servidor en lugar de la variable selectedServer fue mejor. like this.string computername = Environment.GetEnvironmentVariable ("nombre de computadora");
Dave
5

CMS tiene razón, pero también si usa el explorador de servidores en Visual Studio y juega con la pestaña del contador de rendimiento, entonces puede descubrir cómo obtener muchas métricas útiles.

Tarks
fuente
3

Esto parece funcionar para mí, un ejemplo para esperar hasta que el procesador alcance un cierto porcentaje

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();
}
Jay Byford-Rew
fuente
¿Por qué duermes cuando el uso es 0?
watashiSHUN
2

Esta clase sondea automáticamente el contador cada 1 segundo y también es seguro para subprocesos:

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;
    }
}
Colin Breame
fuente
System.DateTimees en realidad un tipo de valor de 8 bytes, lo que significa que las asignaciones a una DateTimevariable no son atómicas. Este código no es seguro para subprocesos en plataformas de 32 bits.
andrewjs
1

No me gustó tener que agregar el puesto de 1 segundo a todas las PerformanceCountersoluciones. En cambio, elegí usar una WMIsolución. La razón por la que existe la espera / parada de 1 segundo es para permitir que la lectura sea precisa al usarPerformanceCounter . Sin embargo, si llama a este método con frecuencia y actualiza esta información, le aconsejaría que no tenga que sufrir ese retraso constantemente ... incluso si está pensando en hacer un proceso asíncrono para obtenerlo.

Comencé con el fragmento desde aquí Devolviendo el uso de la CPU en WMI usando C # y agregué una explicación completa de la solución en la publicación de mi blog a continuación:

Obtenga el uso de la CPU en todos los núcleos en C # con WMI

atconway
fuente
Incluya la respuesta aquí en lugar de vincular a su blog.
Herman
@Herman: no solo hice un enlace a mi blog; Di una explicación primero, y procedí a proporcionar un enlace para una respuesta en profundidad más allá de la publicación aquí.
atconway
La solución en tu blog es como 12 líneas de código. ¿Por qué no incluir eso en su respuesta aparte de tratar de hacer que la gente visite su blog?
Herman
@Herman: ¿Cuál es el problema al hacer clic en el enlace, ya que contiene una explicación detallada; esa es la idea de la elaboración de la porción 'por qué'? También esto tiene 7 años, solo digo. Es difícil recordar esta publicación exacta y que yo era un novato en SO en ese entonces.
atconway
el enlace podría romperse, y es mucho más fácil escanear respuestas cuando el contenido principal está en línea. Perdón por ser duro en mi otra respuesta, no estoy aquí para hacerte pasar un mal rato. :)
Herman
0
public int GetCpuUsage()
{
var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total", Environment.MachineName);
cpuCounter.NextValue();
System.Threading.Thread.Sleep(1000); //This avoid that answer always 0
return (int)cpuCounter.NextValue();
}

Información original en este enlace https://gavindraper.com/2011/03/01/retrieving-accurate-cpu-usage-in-c/

araad1992
fuente