11

I want to have current CPU utilization in my project

namespace Monitoring_Tool
{
    public partial class ajaxExecute : System.Web.UI.Page
    {
        private PerformanceCounter theCPUCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
        private PerformanceCounter theMemCounter = new PerformanceCounter("Memory", "Available MBytes");

        protected void Page_Load(object sender, EventArgs e)
        {
            float cpuUsage = 0.00F;

            cpuUsage = this.theCPUCounter.NextValue();
        }
    }
}

When I debug my project, the value in cpuUsage is showing 0.00 but when I do QuickWatch on this.theCPUCounter.NextValue(); it is showing 20.6786852.

Why can't I store it in a variable?

Null
  • 1,950
  • 9
  • 30
  • 33
Shaggy
  • 5,422
  • 28
  • 98
  • 163
  • 2
    Silly remark, but perhaps you have not yet stepped over the instruction while debugging, so the new value is not yet stored in the `cpuUsage` variable? – Mr47 Aug 23 '13 at 09:03

2 Answers2

11

That's because you need to call NextValue multiple times on the same PerformanceCounter instance (so at least twice). The first call will always return 0.

You can work around this (sort of) by calling NextValue twice in your Page_Load event handler, only storing the return value of the second call:

        float cpuUsage = 0.00F;

        this.theCPUCounter.NextValue();
        cpuUsage = this.theCPUCounter.NextValue();

The reason it shows in the QuickWatch of the debugger is probably just because it is (implicitly) called multiple times (once by the program and once by the debugger for the QuickWatch value).

Update to the "sort of" above:

As others have mentioned you usually need to sleep some time between the two calls to actually observe a difference in CPU load that results in a "measurable" difference. Sleeping for 1 s usually does the trick, but might not be an acceptable delay in the loading of your page.

What you really want to do is provide a background thread that repeatedly queries this performance counter, sleeping a couple of seconds in between. And storing the result somewhere. From your Page_Load or other events / functions query the (last) value. All with necessary locking against data races of course. It will be as accurate as you can get with regards to this pointer.

Since you are obviously using ASP.NET you have to be careful with such background threads. I'm no ASP.NET expert, but according to this it should be possible, even though the thread (and the perf counter readings it did) will be recycled, when your app domain / web application is. However, for this kind of functionality that shouldn't be an issue.

Community
  • 1
  • 1
Christian.K
  • 47,778
  • 10
  • 99
  • 143
  • 1
    "The first call will always return 0." is there a reason for this? – sab669 Sep 04 '15 at 20:17
  • @sab669 Per the [`documentation`](https://msdn.microsoft.com/en-us/library/system.diagnostics.performancecounter.nextvalue.aspx): "If the calculated value of a counter depends on two counter reads, the first read operation returns 0.0". The "% Processor Time" counters require state to give you an answer, and the first call into them have no state to compare against yet so they have it return 0. More info [here](http://stackoverflow.com/a/18399097/5095502). – Quantic Aug 24 '16 at 16:47
  • I've to calculate CPU usage in Windows Service, after getting CPU Reading I'm supposed to send it to a server in JSON format. I'm not in a position to use a separate thread for CPU current usage. Is there no simple function available in C# to get the current CPU usage , like we use in Android ? – Ammar Shaukat Jun 26 '18 at 10:12
  • Apart from using WMI, you might need to p/invoke [`GetSystemTimes`](https://msdn.microsoft.com/de-de/library/windows/desktop/ms724400(v=vs.85).aspx) and [calculate](https://www.codeproject.com/Articles/9113/Get-CPU-Usage-with-GetSystemTimes) from there on. Consider asking a new question - making sure you state that you cannot use PCs (or threads) because of constraints. There might be an answer on SO already. – Christian.K Jun 26 '18 at 11:01
11

It is a performance counter that heavily depends on when you read it. A processor core is either executing code, running full bore at "100%". Or it is turned off completely, stopped by the HALT instruction. The "% Processor Time" counter tells you for how many % of the time, since the last time you checked it, it has been executing code.

So you will only get meaningful values if you wait long enough between sampling it. One second is boilerplate, that's what you see in Perfmon.exe and Taskmgr.exe. The shorter the interval, the less accurate the number gets. It starts to vary wildly, jumping between 0 and 100%.

So getting 0% in the page's Load event is normal, it just initializes the counter to set the start of the interval. Getting the next sample is hardship, you can't realistically do this in the event handler. You'd have to do something drastic like having a separate timer or thread that samples at one second intervals and use that value.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536