Click here to Skip to main content
12,952,398 members (39,481 online)
Click here to Skip to main content
Add your own
alternative version


165 bookmarked
Posted 1 May 2005

How to get CPU usage of processes and threads

, 29 Jan 2006
Rate this:
Please Sign up or sign in to vote.
This article will explain how to calculate the CPU usage efficiently (with low CPU usage).


The CPU usage is often recognized from Windows Task Manager. I will explain in this article the most efficient way I could find to calculate it for both processes and threads.


My journey began when I had to write a Task Manager look alike that also had some netstat features. I searched the web for methods of getting the CPU usage but the best I could find was only advices for using PerformanceCounter("Processor","% Process Time",ProcessName) for monitoring the usage value. I tried it and it's a good method as long as you use only a few (1-3) PerformanceCounters because it consumes a lot of CPU which got me to a usage of 6% - 18% for my own Task Manager for just the refresh operation every 2 seconds.

CPU usage calculation concept

For calculating the CPU usage of processes we need to get a value that indicates for how much time they have used the processor in a certain period of time, this value is equal to the sum of the time that the kernel and the user have spent on these processes, I will demonstrate two ways to achieve this value:

  • the API way - using the GetSystemTimes() function,
  • the managed way - using the System.Diagnostics namespace.

After we get this value, we keep it for the next run (the refresh time is usually 1.5 seconds) we then decrease the new value from the old value and divide it by the refresh time. I know it sounds complicated, the following code will explain it better:

private void CalcCpu()
    // refresh delay 1.5 seconds    
    int RefreshInterval = 1500; 
    // keeps the previous usage value.
    long OldRawUsageValue = GetCurrentUsageValue(); 
    // keeps the current usage value.
    long NewRawUsageValue;
    // holds the cpu usage in a friendly reading way. 
    string CpuUsage; 


    while (KeepCalculation)
        NewRawUsageValue = GetCurrentUsageValue();
        CpuUsage = ((int)((NewRawUsageValue - OldRawUsageValue) / 
                                  RefreshInterval)).ToString() + "%";
        OldRawUsageValue = NewRawUsageValue;

The API approach

After I was left with some bitter taste of the .NET 2.0 changes and some of the comments I got here, I decided to write an API version for this. Surprisingly, I found many C++ articles on this and even some old VB code. I migrated the code by following ejor's article Get CPU Usage with GetSystemTimes. My big thanks go to PInvoke for their contribution to the translated API availability which helped me a lot. This API version does not include the CPU usage of threads (the code is very similar to that of process code); I was too lazy to write it.

For getting the CPU usage, using the API approach, we need a function called GetProcessTimes. This function gets us four parameters CreationTime, ExitTime, KernelTime and UserTime. We won't use the first two, the other two (KernelTime and UserTime) are equivalent to the managed version Process.TotalProcessorTime.TotalMilliseconds, after realizing that this pretty much goes the same way as the managed version, just that it is a bit more difficult to get the GetSystemTimes to work than to use the System.Diagnostic.Process class, but the benefit comes in the way of better performance.

.NET 2.0 style

If you have tried running the old version on .NET 2.0 you'll be surprised to see that what was good enough for .NET 1.1 is not good for .NET 2.0. Well, I don't know why for some reason Microsoft decided not to allow gathering any information about the system idle process (which was allowed in .NET 1.1). Well, for a quick solution, I used a PerformanceCounter, but there is only one instance of it so it keeps the overall performance pretty satisfying. What we do here is use the PerformanceCounter to monitor the idle process CPU usage as we know that the real CPU usage is 100% - idle CPU usage% (you can also do this by monitoring the "_Total" value and 100 - _Total == idle CPU usage).

private static void UpdateCpuUsagePercent(
                           Process[] NewProcessList)
    double Total = 0;
    ProcessInfo TempProcessInfo;
    TotalCpuUsageValue = TotalCpuUsage.NextValue();

    foreach (Process TempProcess in NewProcessList)
        if (TempProcess.Id == 0) continue;
        TempProcessInfo = ProcessInfoByID(TempProcess.Id);
        if (TempProcessInfo == PROCESS_INFO_NOT_FOUND)
          Total += 
          Total += TempProcess.TotalProcessorTime.TotalMilliseconds - 
    CpuUsagePercent = Total / (100 - TotalCpuUsageValue);

The new method

I came up with a new way of calculating 1% of the CPU usage by having it depend on some specific process. What we do here is get all the CPU usage raw (double) values and what we get is the total CPU usage. By dividing this with 100, we get 1%. This method is better because it's not process specific of course, and it even cancels the single PerformanceCounter of the last solution:

private static void UpdateCpuUsagePercent(
                            Process[] NewProcessList)
   double Total = 0;
   ProcessInfo TempProcessInfo;

   foreach (Process TempProcess in NewProcessList)
      TempProcessInfo = ProcessInfoByID(TempProcess.Id);
      if (TempProcessInfo == PROCESS_INFO_NOT_FOUND)
         Total += TempProcess.TotalProcessorTime.TotalMilliseconds;
         Total += TempProcess.TotalProcessorTime.TotalMilliseconds - 
   CpuUsagePercent = Total / 100;

The old method

After breaking my head for two days and thinking of creative ways to achieve a better way to do this, I decided to use a single PerformanceCounter to get some value that will help me calculate the rest of the values.

The solution

I created a PerformanceCounter for the CPU idle process and got its usage %, then I used Process.GetProcesses() to get a Process[] array. The Process class has a property called TotalProcessorTime.TotalMilliseconds which gives us how much time the processor has spent on this process. I save this value and the next time I check it (every 1.5 seconds - the refresh rate), I decrease it from the last value giving me the raw output of how much millisecond equals the idle CPU usage %.

Now by dividing this value with the CPU usage %, I get how much millisecond is 1% of CPU:

private static void UpdateCpuUsagePercent()
    long NewIdleCpuUsage = (long) 

    CpuUsagePercent = IdleCpuUsage.NextValue();
    CpuUsagePercent = 
        (NewIdleCpuUsage - OldIdleCpuUsage) / CpuUsagePercent;
    OldIdleCpuUsage = NewIdleCpuUsage;

Knowing this, I can calculate for each process or thread (which also has the TotalProcessorTime.TotalMilliseconds property) the CPU usage, by dividing its TotalProcessorTime.TotalMilliseconds with the CPU 1%, and the output we get is its CPU usage %:

private static ProcessInfo 
  GetProcessInfo(ProcessInfo TempProcess,Process CurrentProcess)
    long NewCpuUsage = (long) 

    TempProcess.CpuUsage = ((NewCpuUsage - TempProcess.OldCpuUsage) / 
    TempProcess.OldCpuUsage = NewCpuUsage;

    return TempProcess;

Using the code

Choose your own way. I don't know if the API version is always good, it requires much more work than the managed one, but if you are after your own "Task Manager" you should definitely take the API one.


Once again, we take into consideration the performance and ease of coding when we compare managed .NET and the uncomfortable API.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Team Leader
Israel Israel
No Biography provided

You may also be interested in...


Comments and Discussions

QuestionWhy do you need idle usage to get usage for each process? Pin
vbprogr1127-Apr-15 3:59
membervbprogr1127-Apr-15 3:59 
QuestionLicense Type Used Pin
dbhatt7923-Feb-15 6:50
memberdbhatt7923-Feb-15 6:50 
QuestionThe Memory usage of processes Pin
Member 104234016-Jan-14 16:42
memberMember 104234016-Jan-14 16:42 
QuestionHi Gil,Wouldnt this be enough to calculate the average CPU usage of a process? Pin
shaijujanardhanan11-Mar-13 18:15
membershaijujanardhanan11-Mar-13 18:15 
AnswerRe: Hi Gil,Wouldnt this be enough to calculate the average CPU usage of a process? Pin
Matt Watson (Stackify)7-Nov-13 12:09
memberMatt Watson (Stackify)7-Nov-13 12:09 
QuestionAnybody has the complete code? Pin
Member 965297620-Dec-12 8:47
memberMember 965297620-Dec-12 8:47 
AnswerRe: Anybody has the complete code? Pin
Member 104234016-Jan-14 19:11
memberMember 104234016-Jan-14 19:11 
GeneralMy vote of 1 Pin
elvand29-Sep-12 4:47
memberelvand29-Sep-12 4:47 
QuestionIt does not work for Windows 7 64bit? Pin
stevenyoung16-Oct-11 19:34
memberstevenyoung16-Oct-11 19:34 
QuestionPerformance Pin
titan250818-Jul-11 11:18
membertitan250818-Jul-11 11:18 
GeneralMy vote of 4 Pin
auldh2-Jun-11 5:49
memberauldh2-Jun-11 5:49 
GeneralNew code Pin
auldh27-May-11 8:06
memberauldh27-May-11 8:06 
GeneralLove your code- but I cannot build the API version Pin
jlkdaslkfjd28-Apr-11 1:17
memberjlkdaslkfjd28-Apr-11 1:17 
QuestionSomebody Pin
Peregarich1-Feb-11 8:39
memberPeregarich1-Feb-11 8:39 
GeneralAccess Denied Pin
EricLayne8-Aug-10 16:15
memberEricLayne8-Aug-10 16:15 
I am desperately trying to get this code to work. Both of the executables and their source code throw 'Access is Denied' error. Using VS2010 on Win 7. Tried running as administrator but it doesn't work.

I have spent hours searching the Web for a fix, but cannot find anything conclusive. I have tried writing a similar program using API, Managed, and WMI. Only WMI will work but it is slow as molasses without a Refresher, which seems to be missing in C#.

Cry | :(( Cry | :(( Cry | :((

************** Exception Text **************
System.ComponentModel.Win32Exception: Access is denied
at System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.GetProcessTimes()
at System.Diagnostics.Process.get_TotalProcessorTime()
at CpuUsageManaged.ProcessCpu.UpdateCpuUsagePercent(Process[] NewProcessList)
at CpuUsageManaged.ProcessCpu.UpdateProcessList()
at CpuUsageManaged.Example.Updater_Tick(Object sender, EventArgs e)
at System.Windows.Forms.Timer.OnTick(EventArgs e)
at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
GeneralRe: Access Denied Pin
Frank van Bokhoven25-Jan-11 21:53
memberFrank van Bokhoven25-Jan-11 21:53 
GeneralMessage Automatically Removed Pin
8-Aug-10 3:37
memberiranianboy8-Aug-10 3:37 
GeneralInvalid resx file: Cannot run source code in VWD2010 Pin
AndrusM29-Jun-10 7:04
memberAndrusM29-Jun-10 7:04 
GeneralRe: Invalid resx file: Cannot run source code in VWD2010 Pin
0riundo16-Apr-12 23:34
member0riundo16-Apr-12 23:34 
GeneralThanks Pin
anhldbk4-May-10 0:25
memberanhldbk4-May-10 0:25 
Generalcorrection Pin
eip1021-Nov-09 10:38
membereip1021-Nov-09 10:38 
QuestionDoesnt work with Dual Core or Multi CPU machines Pin
Member 47369263-Feb-09 7:37
memberMember 47369263-Feb-09 7:37 
AnswerRe: Doesnt work with Dual Core or Multi CPU machines Pin
maverick9119-Nov-09 3:38
membermaverick9119-Nov-09 3:38 
AnswerRe: Doesnt work with Dual Core or Multi CPU machines Pin
eip1021-Nov-09 10:41
membereip1021-Nov-09 10:41 
AnswerRe: Doesnt work with Dual Core or Multi CPU machines Pin
fuerer9-Aug-11 22:45
memberfuerer9-Aug-11 22:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170525.1 | Last Updated 30 Jan 2006
Article Copyright 2005 by Gil.Schmidt
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid