2012-02-29 10 views
13

Desidero visualizzare l'utilizzo della CPU per la mia applicazione multithread (che funziona su un processore multicore). Voglio ricevere i numeri vicino a Task manager. Ma ho ottenuto numeri superiori al 100%. Anche più del 500%. Sì, lo so, di contatore "% Tempo processore" per la categoria "Processo" ho bisogno di dividere in Environment.ProcessorCount o "NumberOfLogicalProcessors" (stessi per la mia configurazione). E il 500% è un risultato dopo l'operazione. Ho testato questo esempio su diversi computer con hardware diverso (i7, i5, Core2) e configurazioni software (Windows 7 SP1 con tutti gli aggiornamenti, Windows 2008 R2 SP1 con tutti gli aggiornamenti) e ho avuto lo stesso problema.Contatore di prestazioni L'utilizzo della CPU per il processo corrente è superiore a 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; } 
} 

e il codice da eseguire (è necessario creare applicazione Windows Form con due labeles, uno BackgroundWorker e un pulsante)

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

favore, mi mostri il mio errore. E sì, ho letto this article e ho notato che

“\ Process (...) \% Tempo processore” può arrivare fino a N * 100 (dove N è il numero di CPU), perché si aggiunge l'utilizzo della CPU il processo richiesto attraverso tutte le CPU.

+1

Si prega di non copiare il codice del buco nella domanda, solo le linee che sono necessarie per rispondere alla tua domanda. E, naturalmente, lascia dei commenti sul tuo codice. –

risposta

4

This (in qualche modo correlato) domanda suggerisce di utilizzare le proprietà System.Diagnostics.Process.TotalProcessorTime e System.Diagnostics.ProcessThread.TotalProcessorTime invece, a basso overhead e facile implementazione.

(Edit:. Here's an article che spiega come utilizzare le proprietà, come pure)

Inoltre, sembra che non si è in attesa abbastanza a lungo da una chiamata a "_processTimeCounter.NextValue()." Come da the documentation, dovresti aspettare almeno 1 secondo. Non sono sicuro se ciò causerebbe i tuoi numeri strani o no.

+0

Un secondo ritardo tra le chiamate necessarie per i contatori dipende da due letture contatore. Ma questa soluzione funziona bene per il mio codice. Informazioni su System.Diagnostics.ProcessThread.TotalProcessorTime, ho provato a utilizzare questa soluzione in precedenza, ma ho ottenuto uno strano carico della CPU (<10%, che non viene visualizzato il carico effettivo del processo). – user809808

+0

L'articolo che citi è un casino totale: il programma di esempio mostra alcuni valori negativi. Il calcolo in sé comporta il contro per il processo "Idle" per sake sconosciuto. Non ho mai visto più informazioni fuorvianti su SO. Ciò che è essenzialmente deludente è che diverse risposte menzionano questo articolo. – alehro