如何在C#中获取CPU使用率?


Answers:


205

您可以使用System.Diagnostics中PerformanceCounter

像这样初始化:

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

80
不错-但原始来源似乎来自此处:zamov.online.fr/EXHTML/CSharp/CSharp_927308.html
Matt Refghi,2009年

19
从我发现的结果中,我不得不两次使用cpuCounter.NextValue(),并且在它们之间我不得不睡眠(500)
Angel.King.47年

马特是对的。甚至包括错误,例如忘记了“ return”关键字。
2011年

8
是的,它看起来像是该链接的副本,因此,用于引用原始链接的链接将是不错的样式。另一方面,CMS在此处提供答案也很好,因此懒惰的开发人员不必在整个Google上进行搜索即可找到相同的答案。:o)
BerggreenDK

13
您将需要两次调用.NextValue,并在两者之间进行一次System.Threading.Thread.Sleep调用(1000ms就足够了)。有关为何需要这样做的更多信息,请参见blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx,但高级摘要是您需要两个样本才能计算出该值,并且您需要给操作系统一些时间来获得这两个功能。
Cleggy

63

比要求的要多一点,但是我使用额外的计时器代码来跟踪并发出警报,如果持续1分钟或更长时间,CPU使用率是否达到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";
    }
}

7
getRAMCounter()在哪里?
Dieter B

1
cpuCounter.NextValue返回float。那么,为什么将其分配给dynamic?那为什么要把它dynamic作为一个返回object呢?那么,为什么要在行中将objectan 分配给an ?(该代码将无法编译。)intint cpuPercent = getCPUCounter()
Wyck

21

花了一些时间阅读了几个看起来很复杂的不同线程后,我想到了这个。我需要用于要监视SQL Server的8核计算机。对于下面的代码,然后我将“ 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百分比。


total_cpu应该是PerformanceCounter(“ Processor”),而不是PerformanceCounter(“ Process”)..否则,您只会获得100%*内核数。
史蒂夫·库克2014年

3
您在哪里设置done为true?除非我忽略了某些内容,否则这似乎是一个无休止的循环:while(!done){...}
曼弗雷德(Manfred)'18年

@Manfred这确实是一个无休止的循环
珍妮(Jenny)

16

没关系,我知道了!谢谢你的帮助!

这是执行此操作的代码:

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

添加获取服务器名称而不是变量selectedServer更好。像这样。string computername = Environment.GetEnvironmentVariable(“ computername”);
Dave


5

CMS是正确的,但是如果您在Visual Studio中使用服务器资源管理器并使用“性能计数器”选项卡,那么您可以弄清楚如何获得许多有用的指标。


3

这似乎对我有用,例如等待处理器达到一定百分比的示例

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

使用量为0时为什么要睡觉?
watashiSHUN

2

此类每1秒自动轮询一次计数器,并且也是线程安全的:

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位平台上不是线程安全的。
andrewjs '16

1

我不喜欢在所有PerformanceCounter解决方案中增加1秒的停顿时间。相反,我选择使用一种WMI解决方案。1秒等待/停转的原因是为了使使用时的读数准确PerformanceCounter。但是,如果您经常调用此方法并刷新此信息,则建议不要经常发生这种延迟...即使考虑进行异步处理以获取该延迟。

我从此处的代码片段开始,使用C#返回WMI中的CPU使用率,并在下面的博客文章中添加了对该解决方案的完整说明:

使用WMI获取C#中所有内核的CPU使用率


请在此处添加答案,而不是链接到您的博客。
赫曼

@Herman-我不仅链接到我的博客;我首先给出了一个解释,然后继续提供一个链接,供您在此处发表文章后进行深入解答。
atconway,

您博客文章中的解决方案就像12行代码。除了尝试吸引人们访问您的博客外,为什么不将其包含在您的答案中?
赫曼

@Herman-单击链接会有什么问题,因为该链接包含深入的说明;这就是“为什么”详细阐述的想法?也说这是7岁。很难记住这个确切的帖子,那时候我还是新手。
atconway

链接可能会断开,当核心内容为内联时,扫描答案要容易得多。很抱歉在我的其他回复中很苛刻,我在这里不给您带来麻烦。:)
赫尔曼

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.