Como obter o uso da CPU em c #?


Respostas:


205

Você pode usar a classe PerformanceCounter do System.Diagnostics .

Inicialize assim:

PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;

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

Consumir assim:

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

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

80
Nice - mas a fonte original parece ser a partir daqui: zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
— Matt Refghi

19
Pelo que eu descobri, eu tinha que usar cpuCounter.NextValue () duas vezes e entre eles eu tinha que Dormir (500)
— Angel.King

Matt está certo. Mesmo incluindo os erros, como esquecer a palavra-chave "return".
— usar o seguinte código

8
sim, parece uma cópia desse link; portanto, um link para referência do original teria sido um estilo legal. Por outro lado, também é bom que o CMS forneça a resposta aqui, para que desenvolvedores preguiçosos não precisem pesquisar em todo o Google para encontrar a mesma resposta. : o)
— BerggreenDK

13
Você precisará chamar .NextValue duas vezes, com uma chamada System.Threading.Thread.Sleep no meio (1000ms deve ser suficiente). Consulte blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx para obter mais informações sobre por que isso é necessário, mas o resumo de alto nível é que você precisa de duas amostras para calcular o valor, e você precisa dar um tempo ao sistema operacional para obter os dois.
— Cleggy

63

Um pouco mais do que foi solicitado, mas eu uso o código de timer extra para rastrear e alertar se o uso da CPU é 90% ou mais por um período prolongado de 1 minuto ou mais.

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
Onde está o getRAMCounter ()?
— Dieter B

1
cpuCounter.NextValueretorna afloat . Então, por que atribuí-lo a um dynamic? Então, por que retornar isso dynamiccomo um object? Então, por que tentar atribuir um objecta um intna linha int cpuPercent = getCPUCounter()? (Esse código não irá compilar.)
— Wyck

21

Depois de passar algum tempo lendo alguns tópicos diferentes que pareciam bastante complicados, eu vim com isso. Eu precisava dele para uma máquina de 8 núcleos onde queria monitorar o servidor SQL. Para o código abaixo, passei "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 corretamente a% de CPU usada pelo SQL no meu servidor de 8 núcleos.


total_cpu deve ser PerformanceCounter ("Processor"), não PerformanceCounter ("Process"). Caso contrário, você obtém 100% * do número de núcleos.
— Steve Cook

3
Onde você define donea verdade? A menos que eu tenha esquecido alguma coisa, isso parece ser um loop infinito:while(!done){...}
— Manfred

@Manfred Na verdade, é um anel sem fim
— Jenny

16

Está tudo bem, eu entendi! Obrigado pela ajuda!

Aqui está o código para fazer isso:

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

Adicionar a obtenção do nome do servidor em vez da variável selectedServer foi melhor. como este.string nome_do_computador = Environment.GetEnvironmentVariable ("nome_do_computador");
— Dave


5

O CMS está certo, mas também se você usar o server explorer no visual studio e brincar com a guia do contador de desempenho, poderá descobrir como obter muitas métricas úteis.


3

Isso parece funcionar para mim, um exemplo de espera até que o processador atinja uma certa porcentagem

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

por que você está dormindo quando o uso é 0?
— WatsonSHUN

2

Essa classe pesquisa automaticamente o contador a cada 1 segundo e também é segura para threads:

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é na verdade um tipo de valor de 8 bytes, o que significa que as atribuições a uma DateTimevariável não são atômicas. Este código não é seguro para threads em plataformas de 32 bits.
— andrewjs

1

Eu não gostei de ter que adicionar no estande de 1 segundo a todas as PerformanceCountersoluções. Em vez disso, optei por usar uma WMIsolução. A razão pela qual a espera / travamento de 1 segundo existe é permitir que a leitura seja precisa ao usar umPerformanceCounter . No entanto, se você chamar esse método com frequência e atualizar essas informações, aconselho a não ter que sofrer constantemente esse atraso ... mesmo que esteja pensando em fazer um processo assíncrono para obtê-lo.

Comecei com o trecho daqui Retornando o uso da CPU no WMI usando C # e adicionei uma explicação completa da solução no meu blog abaixo:

Obter uso da CPU em todos os núcleos em C # usando WMI


Inclua a resposta aqui em vez de vincular ao seu blog.
— Herman

@ Herman - eu não apenas criei um link para o meu blog; Dei uma explicação primeiro e comecei a fornecer um link para uma resposta detalhada além do post aqui.
— atconway

a solução em seu blog é como 12 linhas de código. Por que não incluir isso em sua resposta, além de tentar levar as pessoas a visitar seu blog?
— Herman

@ Herman - Qual é o problema em clicar no link, pois contém uma explicação detalhada; essa é a ideia da elaboração da porção 'por que'? Também isso tem 7 anos, apenas dizendo. Difícil lembrar esse post exato e eu ser um novato no SO naquela época.
— atconway

o link pode ficar quebrado e é muito mais fácil verificar as respostas quando o conteúdo principal está embutido. Desculpe por ser duro na minha outra resposta, não estou aqui para lhe dar um tempo difícil. :)
— Herman

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.