为什么我的CPU使用率总是为0%

本文关键字:使用率 我的 CPU 为什么 | 更新日期: 2023-09-27 18:07:36

我在form1:

void PopulateApplications()
{
    DoubleBufferedd(dataGridView1, true);
    int rcount = dataGridView1.Rows.Count;
    int rcurIndex = 0;
    foreach (Process p in Process.GetProcesses())
    {
        try
        {
            if (File.Exists(p.MainModule.FileName))
            {
                memoryUsage = Core.getallmemoryusage(p.ProcessName);
                Core.getcpu(p.ProcessName);
                cpuusage = Core.processes;
                var icon = Icon.ExtractAssociatedIcon(p.MainModule.FileName);
                Image ima = icon.ToBitmap();
                ima = resizeImage(ima, new Size(25, 25));
                ima = (Image)(new Bitmap(ima, new Size(25, 25)));
                String status = p.Responding ? "Running" : "Not Responding";
                if (rcurIndex < rcount - 1)
                {
                    var currentRow = dataGridView1.Rows[rcurIndex];
                    currentRow.Cells[0].Value = ima;
                    currentRow.Cells[1].Value = p.ProcessName;
                    currentRow.Cells[2].Value = cpuusage;
                    currentRow.Cells[3].Value = memoryUsage;
                    currentRow.Cells[4].Value = status;
                }
                else
                {
                    dataGridView1.Rows.Add(ima, p.ProcessName,cpuusage,memoryUsage, status);//false, ima, p.ProcessName, status);
                }
                rcurIndex++;
            }
        }
        catch ( Exception e)
        {
            string t = "error";
        }
    }
    if (rcurIndex < rcount - 1)
    {
        for (int i = rcurIndex; i < rcount - 1; i++)
        {
            dataGridView1.Rows.RemoveAt(rcurIndex);
        }
    }
}

现在的方法在form1 PopulateApplications,我调用它从计时器滴答事件每5秒。然后我每次对进程进行循环,并获得内存使用情况和CPU使用情况。这是Core类中内存和CPU的方法。

使用内存方法没有问题。工作又好又快

public static string getallmemoryusage(string processName)
{
    var counter = new PerformanceCounter("Process", "Working Set - Private", processName);
    privateMemeory = (counter.NextValue() / 1024 / 1024).ToString();
    //string.Format("Private memory: {0}k", counter.NextValue() / 1024 / 1024);
    return privateMemeory;           
}

问题在于getcpu方法。我需要使它每1000毫秒睡眠几次获得CPU使用情况。如果我在这个方法上使用一个断点,我将最终得到这个值。问题是当我每5秒调用form1中的方法时,它也每5秒调用并执行此getcpu,这些线程睡眠使其工作非常缓慢。如果我将线程睡眠设置为10ms,它会更快,但然后我在大多数进程上得到0%或100%的使用率。

public static string  getcpu(string name)
{
    var cpuload = new PerformanceCounter("Processor", "% Processor Time", "_Total");
    processes = Convert.ToInt32(cpuload.NextValue()) + "%";
    System.Threading.Thread.Sleep(1000);
    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);
    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);
    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);
    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);
    return processes;
}

为什么我的CPU使用率总是为0%

当测量% Processor Time时,Thread.Sleep(1000)是必需的,因为.NextValue()调用决定了时间,处理器自上次调用.NextValue()以来被使用。有关此计算的更多信息,请查看https://learn.microsoft.com/en-us/archive/blogs/bclteam/how-to-read-performance-counters-ryan-byington。

几个建议:

  1. 由于您正在传递进程的名称,我假设您想要测量单个进程的Processor Time。但是,由于您没有在方法中使用该参数,因此您测量的是总体平均系统处理器时间。

因此,如果您想要测量单个进程的性能,您可以使用如下内容:

public static double GetCpuUsage(Process process)
{
    PerformanceCounter cpuCounter = new PerformanceCounter();
    cpuCounter.CategoryName = "Process";
    cpuCounter.InstanceName = process.ProcessName;
    cpuCounter.CounterName = "% Processor Time";
    // The first call will always return 0
    cpuCounter.NextValue();
    // That's why we need to sleep 1 second 
    Thread.Sleep(1000);
    // The second call determines, the % of time that the monitored process uses on 
    // % User time for a single processor. 
    // So the limit is 100% * the number of processors you have.
    double processorUsagePercent = cpuCounter.NextValue();
    // Hence we need to divide by the number of processors to get the average CPU usage of one process during the time measured
    return processorUsagePercent / Environment.ProcessorCount;
}

请注意计数器类别"Processor""Process"的区别。

  • 为什么你在一行中多次调用.NextValue(),然后只返回最后一个值?所以你的方法太慢了。上例中所示的两种计算方法就足够了。

  • 当您想要监视多个进程时,您不必在每次调用.NextValue()之间等待一秒钟。您只需要确保自上次在特定计数器上调用.NextValue()以来至少已经过了一秒钟。对于多个进程,你可以使用这样的方法:

    public static Dictionary

     // Instantiate a new counter per process
     for(int i = 0; i < processes.Length; i++)
     {
         PerformanceCounter processorTimeCounter = new PerformanceCounter(
             "Process",
             "% Processor Time",
             processes[i].ProcessName);
         // Call NextValue once to have a reference value
         processorTimeCounter.NextValue();
         // Add it to the array
         counters[i] = processorTimeCounter;
     }
     // Sleep one second to have accurate measurement
     Thread.Sleep(1000); 
     // Here we store the processes along with their measurement in a dictionary
     Dictionary<Process, double> cpuUsageDictionary = new Dictionary<Process, double>();
     for (int i = 0; i < counters.Length; i++)
     {
         // Determine CPU usage and divide by the number of cores
         double cpuUsage = counters[i].NextValue() / Environment.ProcessorCount;
         // And now we add one key/value pair per process along with its cpu time measurement
         cpuUsageDictionary.Add(processes[i],  cpuUsage);
     }
     return cpuUsageDictionary;
    

    }