0

I am trying to get the CPU load and wish for as close result as possible to what is shown in Task Manager.

I first tried using WMI which returns a good result but is extremely slow (1-10 seconds to complete.

I am now trying to use GetSystemTimes based on the code here

Here is the code:

  static class ProcessorLogic {
    // calc cpu
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool GetSystemTimes(out FILETIME lpIdleTime, out FILETIME lpKernelTime, out FILETIME lpUserTime);

    static bool bUsedOnce = false;
    static ulong uOldIdle = 0;
    static ulong uOldKrnl = 0;
    static ulong uOldUsr = 0;

    public static int CPUusagePercent() {
      int nRes = -1;

      if (GetSystemTimes(out FILETIME ftIdle, out FILETIME ftKrnl, out FILETIME ftUsr)) {
        ulong uIdle = ((ulong)ftIdle.dwHighDateTime << 32) | (uint)ftIdle.dwLowDateTime;
        ulong uKrnl = ((ulong)ftKrnl.dwHighDateTime << 32) | (uint)ftKrnl.dwLowDateTime;
        ulong uUsr = ((ulong)ftUsr.dwHighDateTime << 32) | (uint)ftUsr.dwLowDateTime;

        if (bUsedOnce) {
          ulong uDiffIdle = uIdle - uOldIdle;
          ulong uDiffKrnl = uKrnl - uOldKrnl;
          ulong uDiffUsr = uUsr - uOldUsr;

          if ((uDiffKrnl + uDiffUsr) != 0) { //Calculate percentage
            nRes = (int)((uDiffKrnl + uDiffUsr - uDiffIdle) * 100 / (uDiffKrnl + uDiffUsr));
          }
        }

        bUsedOnce = true;
        uOldIdle = uIdle;
        uOldKrnl = uKrnl;
        uOldUsr = uUsr;
      }

      return nRes;
    }
  }

The result I get are about 40% of what is shown on Task Manager (running on Intel(R) Core(TM) i7-10850H 2.70GHz 6 cores)

  • What am I doing wrong ?

  • I feel that I am reinventing the wheel here, is there a solid library/project/code to get these results correctly ?

kofifus
  • 17,260
  • 17
  • 99
  • 173
  • 1
    Does this answer your question? [Get CPU and RAM usage](https://stackoverflow.com/questions/33387425/get-cpu-and-ram-usage) and [get current cpu usage using c# in asp.net framework](https://stackoverflow.com/questions/39525340/get-current-cpu-usage-using-c-sharp-in-asp-net-framework) and [C# Calculate CPU usage for one process with multiple instances](https://stackoverflow.com/questions/27527433/c-sharp-calculate-cpu-usage-for-one-process-with-multiple-instances) –  Aug 11 '21 at 08:55
  • Is performancecounter better than getsystimes ? – kofifus Aug 11 '21 at 09:04
  • 1
    I don't know getsystimes. Windows PerformandeCounter [works well](https://github.com/Ordisoftware/Hebrew-Calendar/blob/master/Project/Source/Common/Core/Classes/SystemStatistics.cs) smooth and fine for me on Windows, and even though I don't really understand the hack for multiple process instances it works. And it does not need to call a WinAPi using DllImport. –  Aug 11 '21 at 09:07

2 Answers2

1

This is not a full answer, but you might find it helpful (too long for a comment)

This article https://www.codeproject.com/Articles/9113/Get-CPU-Usage-with-GetSystemTimes

But in the conclusion it says :

there is still one problem. For multiple processor system, you don't have the right information.

So you can also look at this post, which although in is not in C# it should still be helpful for you can help you out. It for example also talks about an undocumented NtQuerySystemInformation function.

https://www.autoitscript.com/forum/topic/151831-cpu-multi-processor-usage-wo-performance-counters/

jason.kaisersmith
  • 8,712
  • 3
  • 29
  • 51
0

As pointed above using performance counters is a much better solution

The keys needed are Processor Information, % Processor Utility & _Total

var PerformanceCounterCPULoad = new PerformanceCounter("Processor Information", "% Processor Utility", "_Total");

// call this every second or so
var percent = (int)PerformanceCounterCPULoad.NextValue(); 
kofifus
  • 17,260
  • 17
  • 99
  • 173