2012-02-29 16 views
13

Chcę wyświetlić użycie procesora dla mojej aplikacji wielowątkowej (działającej na procesorze wielordzeniowym). Chcę otrzymywać liczby w pobliżu Menedżera zadań. Ale mam liczby większe niż 100%. Nawet ponad 500%. Tak, wiem, niż licznika „% czas procesora” dla kategorii „proces” muszę podzielić na Environment.ProcessorCount lub „NumberOfLogicalProcessors” (takie same dla mojej konfiguracji). I 500% to wynik po tej operacji. Przetestowałem ten przykład na różnych komputerach z różnym sprzętem (i7, i5, Core2) i konfiguracjami oprogramowania (Windows 7 SP1 z wszystkimi aktualizacjami, Windows 2008 R2 SP1 z wszystkimi aktualizacjami) i mam ten sam problem.Licznik wydajności Wykorzystanie procesora dla bieżącego procesu jest większe niż 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; } 
} 

i kod do wykonania (trzeba utworzyć aplikację Windows Forms z dwoma labeles, jeden BackgroundWorker i jeden przycisk)

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(); 
    } 

Proszę pokazać mi mój błąd. I tak, czytałem this article i zauważył, że

„\ Process (...) \% Czas procesora” może iść do N * 100 (gdzie n oznacza liczbę procesorów), ponieważ dodaje się użycie procesora żądany proces we wszystkich procesorach.

+1

Proszę nie kopiować kodu otworu do pytania, tylko linie, które są potrzebne, aby odpowiedzieć na twoje pytanie. I oczywiście zostaw kilka uwag na temat twojego kodu. –

Odpowiedz

4

This (nieco pokrewne) pytanie sugeruje, używając System.Diagnostics.Process.TotalProcessorTime i System.Diagnostics.ProcessThread.TotalProcessorTime właściwości zamiast na niskim narzutem i łatwego wdrożenia.

(Edit. Here's an article wyjaśniający, jak korzystać z właściwości, jak również)

Ponadto, wygląda na to, że nie czekamy na tyle długo między połączeniami do "_processTimeCounter.NextValue()." Zgodnie z the documentation powinieneś poczekać co najmniej 1 sekundę. Nie jestem pewien, czy spowodowałoby to twoje dziwne liczby, czy nie.

+0

Jedna sekunda opóźnienia między potrzebami połączeń dla liczników zależy od dwóch odczytów licznika. Ale to rozwiązanie działa dobrze dla mojego kodu. O System.Diagnostics.ProcessThread.TotalProcessorTime, próbowałem używać tego rozwiązania wcześniej, ale dostałem dziwne obciążenie procesora (<10%, to nie wyświetla rzeczywistego obciążenia procesowego). – user809808

+0

Artykuł, o którym wspomniałeś, jest totalnym bałaganem: przykładowy program wyświetla wartości ujemne. Samo obliczenie obejmuje licznik dla procesu "Bezczynności" dla nieznanego dobra. Nigdy nie widziałem bardziej mylących informacji na temat SO. Co jest zasadniczo rozczarowujące, że kilka odpowiedzi wspomina ten artykuł. – alehro

Powiązane problemy