当前进程的性能计数器CPU使用率超过100

本文关键字:使用率 CPU 性能计数器 进程 | 更新日期: 2023-09-27 18:26:05

我想显示我的多线程应用程序(在多核处理器上工作)的CPU使用情况。我想收到接近任务经理的号码。但我得到的数字超过了100%。甚至超过500%。是的,我知道,对于"进程"类别,我需要将其划分为Environment.ProcessorCount"NumberOfLogicalProcessors"(与我的配置相同)。500%是在此操作之后的结果。我在具有不同硬件(i7、i5、Core2)和软件配置(Windows 7 SP1所有更新,Windows 2008 R2 SP1所有更新)的不同计算机上测试了这个例子,但得到了相同的问题。

public static class SystemInfo
{
    private static Process _thisProc;
    private static bool HasData = false;
    private static PerformanceCounter _processTimeCounter;
    private static void Init()
    {
        if (HasData)
            return;
        if (CheckForPerformanceCounterCategoryExist("Process"))
        {
            _processTimeCounter = new PerformanceCounter();
            _processTimeCounter.CategoryName = "Process";
            _processTimeCounter.CounterName = "% Processor Time";
            _processTimeCounter.InstanceName = FindInstanceName("Process");
            _processTimeCounter.NextValue();
        }
        MaximumCpuUsageForCurrentProcess = 0;
        HasData = true;
    }
    private static bool CheckForPerformanceCounterCategoryExist(string categoryName)
    {
        return PerformanceCounterCategory.Exists(categoryName);
    }
    public static string FindInstanceName(string categoryName)
    {
        string result = String.Empty;
        _thisProc = Process.GetCurrentProcess();
        if (!ReferenceEquals(_thisProc, null))
        {
            if (!String.IsNullOrEmpty(categoryName))
            {
                if (CheckForPerformanceCounterCategoryExist(categoryName))
                {
                    PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName);
                    string[] instances = category.GetInstanceNames();
                    string processName = _thisProc.ProcessName;
                    if (instances != null)
                    {
                        foreach (string instance in instances)
                        {
                            if (instance.ToLower().Equals(processName.ToLower()))
                            {
                                result = instance;
                                break;
                            }
                        }
                    }
                }
            }
        }
        return result;
    }
    public static int CpuUsageForCurrentProcess
    {
        get
        {
            Init();
            if (!ReferenceEquals(_processTimeCounter, null))
            {
                int result = (int) _processTimeCounter.NextValue();
                result /= Environment.ProcessorCount; //NumberOfLogicalProcessors //same for me
                if (MaximumCpuUsageForCurrentProcess < result)
                    MaximumCpuUsageForCurrentProcess = result;
                return result;
            }
            return 0;
        }
    }
    public static int MaximumCpuUsageForCurrentProcess { private set; get; }
}

和要执行的代码(您需要创建具有两个标签的windows窗体应用程序,一个BackgroundWorker和一个按钮)

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        IList<Task> tasks = new List<Task>();
        for (int i = 0; i < 10; i++)
        {
            Task t = new Task(() =>
            {
                do {
                    if (backgroundWorker1.CancellationPending)
                        break;
                } while (true);
            });
            t.Start();
            tasks.Add(t);
        }
        Task displayProgress = new Task(() => { do {
                                                    if (backgroundWorker1.CancellationPending)
                                                        break;
                                                    backgroundWorker1.ReportProgress(1);
                                                    Thread.Sleep(10);
                                                } while (true); });
        displayProgress.Start();
        tasks.Add(displayProgress);
        Task.WaitAll(tasks.ToArray());
    }
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        label1.Text = SystemInfo.CpuUsageForCurrentProcess.ToString();
        label2.Text = SystemInfo.MaximumCpuUsageForCurrentProcess.ToString();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = SystemInfo.CpuUsageForCurrentProcess.ToString();
        if (backgroundWorker1.IsBusy)
            backgroundWorker1.CancelAsync();
        else
            backgroundWorker1.RunWorkerAsync();
    }

请告诉我我的错误。是的,我读了这篇文章,注意到

"''Process(…)''%Processor Time"可以高达N*100(其中N是CPU数量),因为它将所有CPU中请求进程的CPU使用量相加。

当前进程的性能计数器CPU使用率超过100

这个(有些相关的)问题建议使用System.Diagnostics.Process.TotalProcessorTime和System.Diagnostics.PprocessThread.TotalProcessorTime属性,以降低开销并易于实现。

(编辑:这是一篇解释如何使用属性的文章。)

此外,在调用"_processTimeCounter.NextValue()"之间等待的时间似乎不够长。根据文档,您应该至少等待1秒。不确定这是否会导致你的奇怪数字。