2012-02-29 33 views
13

Quiero mostrar el uso de la CPU para mi aplicación multithread (trabajando sobre un procesador multinúcleo). Quiero recibir números cerca del administrador de tareas. Pero tengo números más del 100%. Incluso más del 500%. Sí, lo sé, que contador "% tiempo de procesador" para la categoría "Proceso" necesito para dividir en Environment.ProcessorCount o "NumberOfLogicalProcessors" (lo mismo para la configuración de mi). Y el 500% es un resultado después de esta operación. Probé este ejemplo en diferentes computadoras con hardware diferente (i7, i5, Core2) y configuraciones de software (Windows 7 SP1 con todas las actualizaciones, Windows 2008 R2 SP1 con todas las actualizaciones) y tuve el mismo problema.Contador de rendimiento El uso de la CPU para el proceso actual es más de 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; } 
} 

y el código para ejecutar (que necesita para crear aplicación de Windows Forms con dos labeles, uno BackgroundWorker y un botón)

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

Por favor, muéstrame mi error. Y sí, he leído this article y se dio cuenta de que

“\ Proceso (...) \% de tiempo de procesador” puede ir hasta N * 100 (donde N es el número de CPU), ya que se suma el uso de CPU de el proceso solicitado en todas las CPU.

+1

No copie el código de su agujero en la pregunta, solo las líneas que se necesitan para responder a su pregunta. Y, por supuesto, deja algunos comentarios sobre tu código. –

Respuesta

4

This (de alguna manera relacionado) pregunta sugiere el uso de los System.Diagnostics.Process.TotalProcessorTime y System.Diagnostics.ProcessThread.TotalProcessorTime propiedades en cambio, para los gastos indirectos bajos y fácil aplicación.

(Edit:. Here's an article que explica cómo utilizar las propiedades, también)

Además, parece que usted no está esperando el tiempo suficiente entre las llamadas a "_processTimeCounter.NextValue()". Según the documentation, se supone que debes esperar al menos 1 segundo. No estoy seguro si eso causaría sus números extraños o no.

+0

Un segundo retraso entre las necesidades de llamadas para los contadores depende de dos lecturas de contador. Pero esta solución funciona bien para mi código. Acerca de System.Diagnostics.ProcessThread.TotalProcessorTime, intenté usar esta solución antes, pero obtuve una carga de CPU extraña (<10%, que no muestra la carga de proceso real). – user809808

+0

El artículo que menciona es un desastre total: el programa de ejemplo muestra algunos valores negativos. El cálculo en sí implica el contador para el proceso "Inactivo" por sake desconocido. Nunca había visto más información engañosa sobre SO. Lo que es esencialmente decepcionante es que varias respuestas mencionen este artículo. – alehro

Cuestiones relacionadas