2012-02-29 115 views
13

我想显示我的多线程应用程序(使用多核处理器)的CPU使用率。我想要接近任务管理器的号码。但是我的数字超过了100%。甚至超过500%。是的,我知道,比专柜“%处理器时间”的类别“过程”我需要分成Environment.ProcessorCount“NumberOfLogicalProcessors”(同为我的配置)。并且在这个操作后500%是的结果。我在具有不同硬件(i7,i5,Core2)和软件配置(包含所有更新的Windows 7 SP1,包含所有更新的Windows 2008 R2 SP1)的不同计算机上测试此示例,并得到同样的问题。当前进程的性能计数器CPU使用率超过100

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窗体有两个labeles,一个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(); 
    } 

请告诉我我的错误。是的,我读this article,发现

“\程序(......)\%处理器时间”可以达到N * 100(其中N是CPU的数目),因为它增加了CPU的使用所有CPU的请求进程。

+1

请不要复制你的漏洞代码到问题中,只需要回答你的问题。当然,在你的代码上留下一些评论。 – 2012-02-29 16:20:29

回答

4

This(有点关系)问题,建议使用System.Diagnostics.Process.TotalProcessorTimeSystem.Diagnostics.ProcessThread.TotalProcessorTime性质相反,低开销,易于实现。

(编辑:Here's an article解释如何使用性能,以及)

此外,它看起来像你不是在等待足够长的时间调用之间“_processTimeCounter.NextValue()。”根据the documentation,你应该等待至少1秒。不知道这是否会导致你的奇怪的数字。

+0

计数器呼叫需求之间的一秒延迟取决于两个计数器读数。但是这个解决方案适用于我的代码。关于System.Diagnostics.ProcessThread.TotalProcessorTime,我曾尝试过使用此解决方案,但得到奇怪的CPU负载(<10%,这不显示实际的过程负​​载)。 – user809808 2012-02-29 22:07:29

+0

您提到的文章总是一团糟:示例程序显示一些负面的值。计算本身涉及用于未知缘故的“空闲”进程的计数器。我从未在SO上看到更多误导性信息。几个答案提到这篇文章实质上令人失望。 – alehro 2016-09-27 16:22:17