C#如何计算特定应用程序的CPU使用率

39

我正在尝试找出如何获取特定进程的CPU使用率,但只能找到与总体CPU使用率相关的信息。

是否有人知道如何提取特定应用程序的当前CPU使用率百分比?


2
根据PID查找实例的相关信息已经添加。 - Erich Mirabal
5个回答

48

性能计数器 - 进程 - % 处理器时间。

以下是一个简单的样例代码,帮助你理解:

using System;
using System.Diagnostics;
using System.Threading;

namespace StackOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            PerformanceCounter myAppCpu = 
                new PerformanceCounter(
                    "Process", "% Processor Time", "OUTLOOK", true);

            Console.WriteLine("Press the any key to stop...\n");
            while (!Console.KeyAvailable)
            {
                double pct = myAppCpu.NextValue();
                Console.WriteLine("OUTLOOK'S CPU % = " + pct);
                Thread.Sleep(250);
            }
        }
    }
}

根据进程ID查找实例的注意事项:

我不知道是否有更好的方法,希望有人能提供。如果没有,那么以下是一种您可以根据进程ID和进程名称找到正确实例名称的方法。

还有另一个性能计数器(PC)被称为“ID Process”,位于“Process”族中。它返回实例的PID。因此,如果您已经知道了名称(即“chrome”或“myapp”),则可以测试每个实例,直到找到与PID匹配的实例。

每个实例的命名都很简单:“myapp”、“myapp#1”、“myapp#2”等。

...  new PerformanceCounter("Process", "ID Process", appName, true);

当PC值等于PID时,你找到了正确的appName。然后,你可以在其他计数器中使用该appName


你知道这个能否适应进程ID或句柄来工作吗?原因是可能有多个进程在运行,我只对监视其中一个感兴趣。 - Grant
17
在多核机器上,您需要将性能计数器的值除以处理器(或核心)的数量。pct = pct / Environment.ProcessorCount。否则,您可能会得到超过100%的值。 - Isak Savo
11
第142天,仍在寻找“任意键”。 - tdgtyugdyugdrugdr
1
我已经发布了答案,结合了所有方法来检索正确的RAM和CPU使用值。代码已包含在内。 - shytikov
Thread.Sleep 暂停线程(它"挂起")。最好使用 Task.Delay使用 Thread.Sleep() 总是不好吗? - Martin Schneider

18
一个不使用 PerformanceCounter 的方法来计算单个进程的处理器使用率。
using System;
using System.Diagnostics;

namespace cpuusage
{
    class Program
    {
        private static DateTime lastTime;
        private static TimeSpan lastTotalProcessorTime;
        private static DateTime curTime;
        private static TimeSpan curTotalProcessorTime;

        static void Main(string[] args)
        {
            string processName = "OUTLOOK";

            Console.WriteLine("Press the any key to stop...\n");
            while (!Console.KeyAvailable)
            {
                Process[] pp = Process.GetProcessesByName(processName);
                if (pp.Length == 0)
                {
                    Console.WriteLine(processName + " does not exist");
                }
                else
                {
                    Process p = pp[0];
                    if (lastTime == null || lastTime == new DateTime())
                    {
                        lastTime = DateTime.Now;
                        lastTotalProcessorTime = p.TotalProcessorTime;
                    }
                    else
                    {
                        curTime = DateTime.Now;
                        curTotalProcessorTime = p.TotalProcessorTime;

                        double CPUUsage = (curTotalProcessorTime.TotalMilliseconds - lastTotalProcessorTime.TotalMilliseconds) / curTime.Subtract(lastTime).TotalMilliseconds / Convert.ToDouble(Environment.ProcessorCount);
                        Console.WriteLine("{0} CPU: {1:0.0}%",processName,CPUUsage * 100);

                        lastTime = curTime;
                        lastTotalProcessorTime = curTotalProcessorTime;
                    }
                }

                Thread.Sleep(250);
            }
        }
    }
}

您可以循环遍历进程以选择其中一个,或者如果您已经知道其ID,则可以使用此命令而不是GetProcessesByName()

Process p = Process.GetProcessById(123);

16

我从多个答案中整合了信息(尤其是这个),并编写出以下代码,可以基于Windows提供的性能计数器信息获取当前进程的CPU和RAM使用情况:

public object GetUsage()
{
    // Getting information about current process
    var process = Process.GetCurrentProcess();

    // Preparing variable for application instance name
    var name = string.Empty;

    foreach (var instance in new PerformanceCounterCategory("Process").GetInstanceNames())
    {
        if (instance.StartsWith(process.ProcessName))
        {
            using (var processId = new PerformanceCounter("Process", "ID Process", instance, true))
            {
                if (process.Id == (int)processId.RawValue)
                {
                    name = instance;
                    break;
                }
            }
        }
    }

    var cpu = new PerformanceCounter("Process", "% Processor Time", name, true);
    var ram = new PerformanceCounter("Process", "Private Bytes", name, true);

    // Getting first initial values
    cpu.NextValue();
    ram.NextValue();

    // Creating delay to get correct values of CPU usage during next query
    Thread.Sleep(500);

    dynamic result = new ExpandoObject();

    // If system has multiple cores, that should be taken into account
    result.CPU = Math.Round(cpu.NextValue() / Environment.ProcessorCount, 2);
    // Returns number of MB consumed by application
    result.RAM = Math.Round(ram.NextValue() / 1024 / 1024, 2);

    return result;
}

没有任何黑客或猜测的情况下确定实例名称,我还要注意多核心。

检索到的信息与我在进程资源管理器和Visual Studio中看到的信息一致。


嗨@shytikov,非常感谢您提供的有用示例。但是我应该在哪里放置>符号?在方法之前还是之后?先行致谢! - Fernando Pie
与真实数据相比,它们极其不准确。CPU负载(任务管理器)= 0.4%,而您的方法显示为4.6%。内存负载= 45MB,而您的方法显示为8.62MB。 - Emanuel

1

基于shytikov的答案,但是异步和可等待 - 使用Task.Delay而不是Thread.Sleep来避免阻塞线程。

private async Task<dynamic> GetUsageAsync()
{
    var process = Process.GetCurrentProcess();
    var name = string.Empty;

    foreach (var instance in new PerformanceCounterCategory("Process").GetInstanceNames())
    {
        if (instance.StartsWith(process.ProcessName))
        {
            using var processId = new PerformanceCounter("Process", "ID Process", instance, true);
            if (process.Id == (int)processId.RawValue)
            {
                name = instance;
                break;
            }
        }
    }

    var cpu = new PerformanceCounter("Process", "% Processor Time", name, true);
    var ram = new PerformanceCounter("Process", "Private Bytes", name, true);

    cpu.NextValue();
    ram.NextValue();

    await Task.Delay(500);
    dynamic result = new ExpandoObject();

    result.CPU = Math.Round(cpu.NextValue() / Environment.ProcessorCount, 2);
    result.RAM = Math.Round(ram.NextValue() / 1024 / 1024, 2); // MB

    return result;
}

使用方法

dynamic result = await GetUsageAsync();
string stats = $"Memory Usage: {result.RAM} MB, CPU Usage: {result.CPU}%";

0
PerformanceCounter ProcessCPUCounter = new PerformanceCounter();
            ProcessCPUCounter.CategoryName = "Process";
            ProcessCPUCounter.CounterName = "% Processor Time";
            ProcessCPUCounter.InstanceName = "TestServiceName"; 
            ProcessCPUCounter.ReadOnly = true;

t3 = new Timer();
            t3.Tick += new EventHandler(ProcessCPUThread); // Everytime t3 ticks, th2_Tick will be called
            t3.Interval = (1000) * (1);              // Timer will tick evert second
            t3.Enabled = true;                       // Enable the t3
            t3.Start(); 

private void ProcessCPUThread(object sender, EventArgs e)
        {
            try
            {         
                Int32 processCPU = Convert.ToInt32( ProcessCPUCounter.NextValue());

                tbCPUperPrcocess.Text = Convert.ToString(processCPU / Environment.ProcessorCount);
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message.ToString());
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接