//Getting the CPU usage via a PerformanceCounter var cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); cpuCounter.NextValue(); System.Threading.Thread.Sleep(1000); // wait a second to get a valid reading var usage = cpuCounter.NextValue();
Notice that stall for 1 second nested in that code above? As documented here: Retrieving Accurate CPU Usage In C# and as seen in almost all code examples, you must add in that stall in order to get an accurate reading. It appears the 1 second value was not arbitrary either and is required in order for the reading to refresh the value.
Well how many are using this statistic in a static manner that is only shown 1 time ever? Not anyone I'm guessing, which mean this code is a part of a page reload or top level refresh in your app that is occurring often. Then I see some code smell because I don't want to have to wait 1 second every time my main page/form/etc. loads. Thinking async? Might work in a WinForm/WPF situation where this could occur on a separate thread, but if this is a part of a web app say monitoring a server, you could incur this hit on every postback. Also, if the total of processing is still having to wait on this code and everything else is complete in less than 1 second, you will still be delayed in net time of 1 second. Point being, incorporate this code into a separate async process or deal with a 1 second delay for every time called.
I think the better solution here is just to use an alternative method in WMI. I also like this method because you get an array/list back with the reading from each core and then the total from all cores. The following WMI code snippet I found can be used to get the CPU core usage values:
//Get CPU usage values using a WMI query ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_PerfFormattedData_PerfOS_Processor"); var cpuTimes = searcher.Get() .Cast<managementobject>() .Select(mo => new { Name = mo["Name"], Usage = mo["PercentProcessorTime"] } ) .ToList();
The thing is I didn't really know what to do with this information at 1st until I dug into it. The List returned will contain the current CPU usage for each core on the processor (1..n) and the total average of all cores. This is the value I'm interested in, and is represented as the last item in the List returned with the name "_Total". Here is the remaining code to get the CPU usage as a single value:
//The '_Total' value represents the average usage across all cores, //and is the best representation of overall CPU usage var query = cpuTimes.Where(x => x.Name.ToString() == "_Total").Select(x => x.Usage); var cpuUsage = query.SingleOrDefault();
If you want to verify the values, add up each core's value in the cpuTimes List and then divide by the total number of cores to get the "_Total" value.
Gorgeous!
ReplyDeleteThis looks cool in theory, unfortunately the code doesn't work. The line ".Cast()" indicates managementobject isn't recognized.. and even if I capitalize it properly, ie ManagementObject, visual studio shows this error: "'System.Management.ManagementObjectCollection' does not contain a definition for 'Cast' and the best extension method overload 'System.Data.EnumerableRowCollectionsExtensions.Cast(System.Data.EnumerableRowCollection)' has some invalid arguments"
ReplyDeleteOtherwise it looked like a neat idea..
You will need to add a reference to System.Linq because the .Cast method on an enumerable is in System.Linq.Enumerable.Cast<TResult> Add using System.Linq; and that code should be resolved.
ReplyDeleteOhh of course, I figured it would be something like a missing reference; thanks :)
ReplyDeleteThanks for that one. much better without that "sleep" :-)
ReplyDeleteI'm not a real programmer, just able to tweak existing codes to do things I need.
I looked around how to do the same thing (WMI) for network bandwidth utilization, but no change I did worked.
If you can, and know how, can you please post how to change your code in order to get network bandwidth thru WMI?
If its easy to get "total" and "per process" that would be super.
Thanks.
TC
@TC - I don't have the code written to use WMI to capture network bandwidth, but I found a link containing some samples and additional links that may help you: http://social.msdn.microsoft.com/Forums/en-US/7bc5c776-88af-4479-ba35-2ef43cebf4ee/logic-to-monitor-internet-bandwidth-usage?forum=csharpgeneral
ReplyDeleteHi folks,
ReplyDeletelook into stackoverflow
http://stackoverflow.com/questions/9777661/returning-cpu-usage-in-wmi-using-c-sharp
You were very close to the correct solution. Thanks for the idea!
Hi Allen,
ReplyDeleteyou were very close to usable soltion.
Look here:
http://stackoverflow.com/questions/9777661/returning-cpu-usage-in-wmi-using-c-sharp
Thanks for the idea
Hi Allen,
ReplyDeleteIs there a way to view this information for a particular application instead of all processes.
Thanks
Hi Allen,
ReplyDeleteThanks for posting this. Perfect solution for what I needed.
Best,
Dax
Some time later... What about disposal of the management objects? Is this not required as they implement IDisposable. How about the following:
ReplyDeletepublic static int TotalUsage
{
get
{
//Get CPU usage values using a WMI query
using (var searcher = new ManagementObjectSearcher("select PercentProcessorTime from Win32_PerfFormattedData_PerfOS_Processor where Name='_Total'"))
{
using (var moc = searcher.Get())
{
var usage = int.Parse(
moc
.Cast()
.FirstOrDefault()
.GetPropertyValue("PercentProcessorTime").ToString()
);
return usage;
}
}
}
}
Can we have a vb.net code for this?
ReplyDeleteThank you,
Hi,
ReplyDeleteThanx for the post
I have gone through above mentioned methods but the value return by PerformanceCounter(NextValue()) and WMI(PercentProcessorTime)
is not matching with the Task Manager , There might be some sort of calculation needed to get the value like TaskManager for Indivual process.
Can please help..
read the 3rd comment fromm below ref link, But i dont know what thet are saying
https://social.technet.microsoft.com/Forums/en-US/0435e7c5-3cda-41a0-953e-7fa462fde03b/perfmon-process-processor-time-vs-task-managers-cpu-usage-for-monitoring-a-specific-user?forum=perfmon