我想在C#中获取应用程序的总CPU使用率。我已经找到了许多深入进程属性的方法,但我只想要进程的CPU使用率和像在任务管理器中获得的总CPU使用率。
如何实现这个功能?
如何实现这个功能?
PerformanceCounter cpuCounter;
PerformanceCounter ramCounter;
cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
像这样消费:
public string getCurrentCpuUsage(){
return cpuCounter.NextValue()+"%";
}
public string getAvailableRAM(){
return ramCounter.NextValue()+"MB";
}
虽然有点超出要求,但我使用额外的计时器代码来跟踪并在CPU使用率持续1分钟或更长时间达到90%或更高时发出警报。
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
返回一个浮点数。那么为什么要将它赋值给一个dynamic
?然后为什么将该dynamic
作为object
返回?然后为什么尝试在行int cpuPercent = getCPUCounter()
中将一个object
分配给一个int
?(这段代码无法编译。) - Wyck在阅读了几个看起来非常复杂的线程后,我想出了这个方法。我需要在一台8核的机器上监控SQL服务器。对于下面的代码,我将"sqlservr"作为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);
}
}
看起来它能够正确地测量在我的8核服务器上SQL正在使用的CPU百分比。
没问题,我明白了!谢谢你的帮助!
这是实现它的代码:
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;
}
CMS做得没错,但是如果您使用Visual Studio中的服务器资源管理器并在性能计数器选项卡中尝试一下,就可以找到很多有用的指标。
对于那些仍无法获得与任务管理器相匹配的总CPU使用率数据的人,您应该使用此语句:
new PerformanceCounter("Processor Information", "% Processor Utility", "_Total");
这个类会自动每秒钟轮询计数器,并且是线程安全的:
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
实际上是一个 8 字节的值类型,这意味着对 DateTime
变量的赋值不是原子性的。在 32 位平台上,此代码不是线程安全的。 - andrewjsaid对我来说,这似乎是有效的。以下是等待处理器达到一定百分比的示例:
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();
}
我不喜欢在所有PerformanceCounter
解决方案中添加1秒的停顿。相反,我选择使用WMI
解决方案。存在1秒的等待/停顿是为了在使用PerformanceCounter
时使读取准确。但是,如果您经常调用此方法并刷新此信息,我建议您不要不断遭受延迟...即使考虑使用异步进程来获取它。
我从这里的片段开始Returning CPU usage in WMI using C#,并在我的博客文章中添加了完整的解决方案说明: