Desejo obter o uso total total da CPU para um aplicativo em C #. Encontrei muitas maneiras de explorar as propriedades dos processos, mas quero apenas o uso da CPU e a CPU total como você obtém no TaskManager.
Como faço isso?
Desejo obter o uso total total da CPU para um aplicativo em C #. Encontrei muitas maneiras de explorar as propriedades dos processos, mas quero apenas o uso da CPU e a CPU total como você obtém no TaskManager.
Como faço isso?
Respostas:
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";
}
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";
}
}
cpuCounter.NextValue
retorna afloat
. Então, por que atribuí-lo a um dynamic
? Então, por que retornar isso dynamic
como um object
? Então, por que tentar atribuir um object
a um int
na linha int cpuPercent = getCPUCounter()
? (Esse código não irá compilar.)
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.
done
a verdade? A menos que eu tenha esquecido alguma coisa, isso parece ser um loop infinito:while(!done){...}
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;
}
Você pode usar o WMI para obter informações de porcentagem da CPU. Você pode até fazer login em um computador remoto se tiver as permissões corretas. Consulte http://www.csharphelp.com/archives2/archive334.html para ter uma idéia do que você pode realizar.
Também útil pode ser a referência do MSDN para o espaço para nome Win32_Process .
Veja também um exemplo do CodeProject Como: (Quase) tudo no WMI via C # .
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();
}
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 DateTime
variável não são atômicas. Este código não é seguro para threads em plataformas de 32 bits.
Eu não gostei de ter que adicionar no estande de 1 segundo a todas as PerformanceCounter
soluções. Em vez disso, optei por usar uma WMI
soluçã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:
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();
}
Informações originais neste link https://gavindraper.com/2011/03/01/retrieving-accurate-cpu-usage-in-c/