While trying to build a task-manager type tool, I noticed that the idle task on my machine sometime consumed over 100% of the CPU!  160%, even 180%.  What's going on?  I asked the base-class framework team and they've clued me in:

Process and Processor have different aggregation types.

 

·         “\Process(…)\% Processor Time” can go up to N*100 (where N is the number of CPUs) because it adds up the CPU usage of the requested process across all the CPUs.

·         “\Process(_Total)\% Processor Time” should always be around N*100 (where N is the number CPUs) because it adds up the CPU usage of each process, including the idle process.

·         “\Processor(…)\% Processor Time” can go up to 100 because it’s the CPU usage of the requested CPU.

·         “\Processor(_Total)\% Processor Time” can go up to 100 because it’s the average CPU usage across all CPUs.

In the above, Process(...) indicates a particular instance of the perf counter, pertaining to a particular process on the machine.  If you have a dual-core machine or a multi-cpu machine - these days even basic laptops have Core Duos - then you will see this behavior.  

Note: this assumes your code uses NextValue(), not NextSample.  Something like this:

    1     public class MyProcessInfo : INotifyPropertyChanged, IDisposable

    2     {

    3         System.Diagnostics.Process _p;

    4         System.Diagnostics.PerformanceCounter _perfCounter;

    5         public MyProcessInfo(System.Diagnostics.Process p)

    6         {

    7             _p = p;

    8             _Id = p.Id;

    9             _WorkingSetInKbytes = p.WorkingSet64 / 1024;

   10             _perfCounter =

   11                 new System.Diagnostics.PerformanceCounter("Process",

   12                     "% Processor Time",

   13                     p.ProcessName,

   14                     true);

   15             _perfCounter.NextValue();

   16         }

   17 

   18         public void UpdateUtilization()

   19         {

   20             CpuUtilization = (int)(_perfCounter.NextValue());

   21         }

Keep in mind that you need to delay "about 1 second" between calls to NextValue(), as per the documentation!