【问题标题】:Why am I getting a CPU usage of 0% all the time?为什么我的 CPU 使用率一直为 0%?
【发布时间】:2014-06-27 21:34:10
【问题描述】:

这就是我在 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 并执行此操作,并且这些线程睡眠使其工作非常缓慢。如果我将线程睡眠设置为 10 毫秒,它会更快,但我会在大多数进程上使用 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;
}

【问题讨论】:

  • Rotem 是的,我用更新的 getcpu 方法使用 name 变量改变了我的问题,并且我没有在 form1 中再次迭代所有进程。我仍然在每个过程中得到 0%。例如,在测试列表中,我看到 1 个索引和:chorme CPU0% 并且每个进程都相同。
  • 在 getcpu 方法中我没有得到异常,我添加了 try and catch now no exceptions。但是在 form1 中,它有时会在某些进程访问被拒绝时抛出异常,但这些是系统进程,所以我不介意他们被拒绝访问。
  • 我刚刚再次更新了我的问题,显示内存使用部分没有问题。仍然 cpu 使用不工作。
  • 用我现在在问题底部尝试的内容再次更新了我的问题。尝试了另一种解决方案,但它也不起作用。尝试了这个解决方案:stackoverflow.com/questions/2181828/… 但是我如何使用 getcpu 方法中的进程名称以及现在在哪里使用? (变量名)
  • 除了您需要将结果除以处理器数量(即 System.Environment.ProcessorCount)这一事实之外,我认为您的代码没有任何问题,它对我有用。如果您尝试获取 % 空闲时间(即传入“Idle”作为第三个参数而不是处理器名称或“_Total”)会发生什么

标签: c# .net winforms


【解决方案1】:

测量% Processor Time 时,需要Thread.Sleep(1000),因为.NextValue() 调用确定了自上次调用.NextValue() 以来使用处理器的时间。有关此计算的更多信息,请查看http://blogs.msdn.com/b/bclteam/archive/2006/06/02/618156.aspx

几个建议:

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

因此,如果您想衡量单个进程的性能,您可以使用类似的方法:

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" 之间的区别。

2) 为什么你连续多次调用.NextValue() 然后只返回最后一个值?这使您的方法如此缓慢。上面例子中的两个计算就足够了。

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

public static Dictionary<Process, double> GetCpuUsages(Process[] processes)
{
    // One performance counter is required per process
    PerformanceCounter[] counters = new PerformanceCounter[processes.Length];

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

【讨论】:

    猜你喜欢
    • 2011-01-12
    • 1970-01-01
    • 2016-04-22
    • 2020-01-27
    • 2018-02-11
    • 2012-10-09
    • 2022-12-05
    • 2020-06-02
    • 1970-01-01
    相关资源
    最近更新 更多