2012-02-29 114 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