I am trying to get the NextValue
of a PerformanceCounter
class using PhysicalDisk
. Some reason that I can't seem to find out why, it return's 0
every time.
PerformanceCounter pcDiskTime = new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total");
Single sinDisk = pcDiskTime.NextValue(); //returns 0.0
Using the above and calling pcDiskTime.NextValue
return's 0
. I have other counter's that are working just fine and return what I need.
.RawValue
does return something, but is not the value I would need. Is there something obvious that I am not doing?
Note: I have verified through Performance Monitor
these are indeed the correct category, counter name and instance name. I have also tried to call .NextValue()
twice as sometimes the first return's 0.0
, but this does not help.
First time it will return zero because there is no previous value to compare, do as below.
PerformanceCounter pcDiskTime = new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total");
//first time call
float perfCounterValue = pcDiskTime.NextValue();
//wait some time
System.Threading.Thread.Sleep(1000);
//get the value again
perfCounterValue = pcDiskTime.NextValue();
If the calculated value of a counter depends on two counter reads, the
first read operation returns 0.0. Resetting the performance counter
properties to specify a different counter is equivalent to creating a
new performance counter, and the first read operation using the new
properties returns 0.0. The recommended delay time between calls to
the NextValue method is one second, to allow the counter to perform
the next incremental read.
This problem annoyed me as well. There were a couple problems that seemed like there should be an easy package to solve but I didn't see one. The first is of course that a value of 0 on the first request is useless. Since you already know that the first response is 0, why doesn't the function just take that into account and return the true .NextValue()?
The second problem is that an instantaneous reading may be wildly inacurrate when trying to make decisions on what resources your app may have available to it since it could be spiking, or between spikes.
My solution was to do a for loop that cycles through and gives you an average for the past few seconds. you can adjust the counter to make it shorter or longer (as long as it is more than 2).
public static float ProcessorUtilization;
public static float GetAverageCPU()
{
PerformanceCounter cpuCounter = new PerformanceCounter("Process", "% Processor Time", Process.GetCurrentProcess().ProcessName);
for (int i = 0; i < 11; ++i)
{
ProcessorUtilization += (cpuCounter.NextValue() / Environment.ProcessorCount);
}
// Remember the first value is 0, so we don't want to average that in.
Console.Writeline(ProcessorUtilization / 10);
return ProcessorUtilization / 10;
}