How to continuously check for CPU usage in C#? - c#

I mainly followed what was discussed in the second answer to this thread. I want to run a program that will continuously check for CPU usage above 5% for 10 seconds and alert me every time it happens.
How to get the CPU Usage in C#?
And my code is as follows:
static void Main(string[] args)
{
Console.WriteLine("Checking for CPU usage");
int totalhits = 0;
float cpuPercent = getCPUValue();
while (true)
{
if (cpuPercent >= 5)
{
totalhits += 1;
if (totalhits == 10)
{
Console.WriteLine("Alert Usage has exceeded");
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
totalhits = 0;
}
}
else
{
totalhits = 0;
}
}
}
private static float getCPUValue()
{
PerformanceCounter cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor time";
cpuCounter.InstanceName = "_Total";
float firstValue = cpuCounter.NextValue();
System.Threading.Thread.Sleep(50);
float secondValue = cpuCounter.NextValue();
return secondValue;
}
My problem is that it never hits that threshold and if I take out the totalhits = 0; statement inside the innermost if statement then it hits the threshold in less than 5 seconds.
What am I doing wrong?

First of all the
float cpuPercent = getCPUValue();
line should be inside the loop. Otherwise you will read the CPU usage only once. and will iterate over the same value.
You should create Only one PerformanceCounter object, and just call cpuCounter.NextValue() again and again inside the loop.
DON'T create the same CPU PerformanceCounter in every iteration.
PerformanceCounter counter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
while (true)
{
float cpuPercent = counter.nextValue();
if (cpuPercent >= 5)
{
totalhits += 1;
if (totalhits == 10)
{
Console.WriteLine("Alert Usage has exceeded");
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
totalhits = 0;
}
}
else
{
totalhits = 0;
}
}
As stated in MSDN
To obtain performance data for counters that required an initial or previous value for performing the necessary calculation, call the NextValue method twice and use the information returned as your application requires.
So you should call the cpuCounter.NextValue() twice (with about a 1 second delay between the calls) to start getting correct CPU Usage results.
BTW, You should wait about a 1 second between each read operation from the CPU PerformanceCounter (to ensure update).
As shown in this post Retriving Accurate CPU Usate In C#

Use the DispatcherTimer as stated in the below msdn and get the results as you needed.
DispatcherTimer

Related

Getting the correct execution timings of a C# method using the StopWatch class

I have been using stopwatch in one of my DevExpress based application. I have created a FlaUI based test case that initiates the keyboard, enters a value and then moves to the next column. Now, there are like 20+ columns in a row in the DevExpress grid I am using. While I try to run that test case 5 times to come to a baseline timing, I am seeing too much different results.
I am pasting an extract of my current code here:
public bool CreateNewGdistVoyageForPerformanceTesting(IEnumerable<GdistBenchVoyageParameters> gdistparameters,
string gridAutomationId)
{
var watch = System.Diagnostics.Stopwatch
.StartNew(); //This line of code is being used to monitor the time taken by each Keyboard operation
long TotalTimeConsumed = 0;
int MaxAllowedTime = 0;
int HasTimeExceeded = 0;
bool TimeHasNotExceeded = true;
watch.Start();
_logger.Info("Creating a new GDIST Voyage");
TabItem ParentControl = VoyageEditorTabControl.SelectedTabItem;
var CurrentSelectedTab = VoyageEditorTabControl.SelectedTabItemIndex;
var ParentGrid = VoyageEditorTabControl.TabItems[CurrentSelectedTab]
.FindFirstDescendant(cf => cf.ByAutomationId(gridAutomationId)).AsGrid();
_controlAction.Highlight(ParentGrid);
var Pattern = ParentGrid.Patterns.Grid;
var RowCount = Pattern.Pattern.RowCount;
var ColumnCount = Pattern.Pattern.ColumnCount;
_logger.Info("======================================================================================");
if (ParentGrid.AutomationId.Equals("ParentGridControl"))
{
_logger.Info($"Performance Testing on GDIST's View Main Grid :{gridAutomationId}");
_logger.Info($"Current Grid Row count is: {RowCount}");
_logger.Info("Creating a new voyage for GDIST Bench");
}
else
{
_logger.Info($"Performance Testing on GDIST's Similar Voyages Panel Grid: {gridAutomationId}");
_logger.Info($"Current Grid Row count is: {RowCount}");
_logger.Info("Editing an existing voyage for GDIST Bench's Similar Voyages Panel");
}
for (int i = 0; i < ColumnCount; i++)
{
var cell = ParentGrid.Patterns.Grid.Pattern.GetItem(ParentGrid.RowCount - 1, i);
if (cell == null)
{
_logger.Warning("No Columns found with matching Automation Ids");
break;
}
if (cell.AutomationId.Equals("Vessel"))
{
MaxAllowedTime = 1500;
gdistparameters.ToList().ForEach(voyageDetailsField =>
{
if (voyageDetailsField.VesselId != null)
{
_logger.Info("Adding Data in Vessel ID ");
cell.Focus();
cell.Click();
_logger.Info($"Entered value is:{voyageDetailsField.VesselId}");
watch.Stop(); // trying this to ensure the watch dummy run to remove JIT noise
if (!watch.IsRunning)
{
watch.Restart(); //starting the watch
}
Keyboard.Type(voyageDetailsField.VesselId.Trim());
watch.Stop();
Keyboard.Press(VirtualKeyShort.TAB);
// _controlAction.WaitFor(new TimeSpan(0, 0, 2));
Wait.UntilInputIsProcessed();
_logger.Info($"Execution Time: {watch.ElapsedMilliseconds} ms");
if (watch.ElapsedMilliseconds > MaxAllowedTime)
{
HasTimeExceeded++;
_logger.Warning($"The data entry time has exceeded beyond the fixed value by {watch.ElapsedMilliseconds - MaxAllowedTime} ms");
}
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
});
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
if (cell.AutomationId.Equals("LoadDate")) //Load Date
{
MaxAllowedTime = 500;
gdistparameters.ToList().ForEach(voyageDetailsField =>
{
// _logger.Info("Adding data into the Load Date field");
if (voyageDetailsField.LoadDate != null)
{
_logger.Info("Adding Data in Load Date ");
cell.Focus();
cell.Click();
_logger.Info($"Entered value is:{voyageDetailsField.LoadDate}");
watch.Stop(); // trying this to ensure the watch dummy run to remove JIT noise
if (!watch.IsRunning)
{
watch.Restart(); //starting the watch
}
Keyboard.Type(voyageDetailsField.LoadDate.Trim());
watch.Stop();
Keyboard.Press(VirtualKeyShort.TAB);
// _controlAction.WaitFor(new TimeSpan(0, 0, 2));
Wait.UntilInputIsProcessed();
_logger.Info($"Execution Time: {watch.ElapsedMilliseconds} ms");
if (watch.ElapsedMilliseconds > MaxAllowedTime)
{
HasTimeExceeded++;
_logger.Warning(
$"The data entry time has exceeded beyond the fixed value by {watch.ElapsedMilliseconds - MaxAllowedTime} ms");
}
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
});
TotalTimeConsumed = TotalTimeConsumed + watch.ElapsedMilliseconds;
}
The timings that I have been observing via the logger functionality is below.
I have run this on multiple PCs, multiple environments but the results are very different. The 5th run is actually taking a lot in every single case.
Note also that all the data that is being entered in populated when the application loads so network latency shouldn't be a problem here.
Moreover, I read that StopWatch comes with a lot of JIT noise, and yes, I had experienced it every time it was running for the first time, so I have already given it a false start in my code.
This test is a performance test and requires benchmarking. We can decide on the benchmarking with such big difference in the numbers.

Trying To Pull CPU & Network Usage Information From Performance Monitor

I'm trying to get CPU and network usage information from a process.In my example, I will use the process chromeHere is how im calling the method using an IEnumerable<String>
foreach (string p in GetProcessStatistics(new string[] { "chrome" }))
{
Console.WriteLine(p);
}
And here is the method.
private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
{
Process[] processList = Process.GetProcesses();
foreach (string process in processesTosearch)
{
foreach (Process p in processList)
{
if (p.ProcessName == process)
{
StringBuilder sb = new StringBuilder();
PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
double cpuData = CPUperformanceCounter.NextValue();
PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);
double networkData = NETWORKperformanceCounter.NextValue();
sb.AppendLine("ID: " + p.Id.ToString());
sb.AppendLine("NAME: " + p.ProcessName);
sb.AppendLine("CPU USAGE: " + cpuData);
sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
sb.AppendLine("NETWORK USAGE: " + networkData);
yield return sb.ToString();
}
}
}
}
And here is the output of one of the results
ID: 17624
NAME: chrome
CPU USAGE: 0
RAM USAGE: 23.2MB
NETWORK USAGE: 0
When I look at Performance Monitor, the cpu and network values are not 0, however in the console, they are.I understand from some research that the values will never be perfect, but why are they showing 0 in the console application and not on performance monitor?
You'll need at least two reads for every counter, at least a second apart to get a usable reading.
Rearrange as needed but you would need to do something like this:
private static IEnumerable<String> GetProcessStatistics(String[] processesTosearch)
{
Process[] processList = Process.GetProcesses();
foreach (string process in processesTosearch)
{
foreach (Process p in processList)
{
if (p.ProcessName == process)
{
StringBuilder sb = new StringBuilder();
PerformanceCounter CPUperformanceCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
PerformanceCounter NETWORKperformanceCounter = new PerformanceCounter("Process", "IO Data Operations/Sec", p.ProcessName);
// set a baseline
CPUperformanceCounter.NextValue();
NETWORKperformanceCounter.NextValue();
Thread.Sleep(1000);
double cpuData = CPUperformanceCounter.NextValue();
double networkData = NETWORKperformanceCounter.NextValue();
sb.AppendLine("ID: " + p.Id.ToString());
sb.AppendLine("NAME: " + p.ProcessName);
sb.AppendLine("CPU USAGE: " + cpuData);
sb.AppendLine("RAM USAGE: " + ConvertToReadableSize(p.PrivateMemorySize64));
sb.AppendLine("NETWORK USAGE: " + networkData);
yield return sb.ToString();
}
}
}
}
I like Jeff's solution, but for me I wanted an average. There were a couple problems getting CPU utilization 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;
}

Get CPU and RAM usage

I need to get the ram memory and CPU usage during execution of a process (the process can run sometimes and over 30 minutes). I am able to get the free RAM but the CPU usage it's not correct, compared with the value from task manager. Am I doing something wrong? Here is my code:
class Program
{
static List<float> AvailableCPU = new List<float>();
static List<float> AvailableRAM = new List<float>();
protected static PerformanceCounter cpuCounter;
protected static PerformanceCounter ramCounter;
static void Main(string[] args)
{
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
try
{
System.Timers.Timer t = new System.Timers.Timer(1200);
t.Elapsed += new ElapsedEventHandler(TimerElapsed);
t.Start();
Thread.Sleep(10000);
}
catch (Exception e)
{
Console.WriteLine("catched exception");
}
Console.ReadLine();
}
public static void TimerElapsed(object source, ElapsedEventArgs e)
{
float cpu = cpuCounter.NextValue();
float ram = ramCounter.NextValue();
Console.WriteLine(string.Format("CPU Value: {0}, ram value: {1}", cpu, ram));
AvailableCPU.Add(cpu);
AvailableRAM.Add(ram);
}
}
But when I run the program, here is what it's printed to the console, compared with values from task manager:
What am I doing wrong?
There is nothing wrong with your values.
The reason you see differences with what task manager returns is that the "CPU usage" value is something computed for a given interval, i.e. between two NextValue() calls. If task manager "doesn't call its own NextValue" (if we simplify how it works) at the same time you do, you won't return the same results.
Imagine the following scenario:
Time 0: 0% actual CPU usage
Time 1: 50% actual CPU usage
Time 2: 70% actual CPU usage
Time 3: 2% actual CPU usage
Time 4: 100% actual CPU usage
If you check the value between Time 1 and Time 3, you'll return something based on "50% and 2%".
If task manager checks the value between Time 2 and Time 4, it'll return something different, i.e. a value based on "70% and 100%".
You could try to spawn multiple processes of your own application, you should also see different results.
Here is what I've found: I've created a list with PerformanceCounter objects for each core, I add the percent and divide the result at number of phisical cores:
class Program
{
static List<float> AvailableCPU = new List<float>();
static List<float> AvailableRAM = new List<float>();
protected static PerformanceCounter cpuCounter;
protected static PerformanceCounter ramCounter;
static List<PerformanceCounter> cpuCounters = new List<PerformanceCounter>();
static int cores = 0;
static void Main(string[] args)
{
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
{
cores = cores + int.Parse(item["NumberOfCores"].ToString());
}
ramCounter = new PerformanceCounter("Memory", "Available MBytes");
int procCount = System.Environment.ProcessorCount;
for(int i = 0; i < procCount; i++)
{
System.Diagnostics.PerformanceCounter pc = new System.Diagnostics.PerformanceCounter("Processor", "% Processor Time", i.ToString());
cpuCounters.Add(pc);
}
Thread c = new Thread(ConsumeCPU);
c.IsBackground = true;
c.Start();
try
{
System.Timers.Timer t = new System.Timers.Timer(1200);
t.Elapsed += new ElapsedEventHandler(TimerElapsed);
t.Start();
Thread.Sleep(10000);
}
catch (Exception e)
{
Console.WriteLine("catched exception");
}
Console.ReadLine();
}
public static void ConsumeCPU()
{
int percentage = 60;
if (percentage < 0 || percentage > 100)
throw new ArgumentException("percentage");
Stopwatch watch = new Stopwatch();
watch.Start();
while (true)
{
// Make the loop go on for "percentage" milliseconds then sleep the
// remaining percentage milliseconds. So 40% utilization means work 40ms and sleep 60ms
if (watch.ElapsedMilliseconds > percentage)
{
Thread.Sleep(100 - percentage);
watch.Reset();
watch.Start();
}
}
}
public static void TimerElapsed(object source, ElapsedEventArgs e)
{
float cpu = cpuCounter.NextValue();
float sum = 0;
foreach(PerformanceCounter c in cpuCounters)
{
sum = sum + c.NextValue();
}
sum = sum / (cores);
float ram = ramCounter.NextValue();
Console.WriteLine(string.Format("CPU Value 1: {0}, cpu value 2: {1} ,ram value: {2}", sum, cpu, ram));
AvailableCPU.Add(sum);
AvailableRAM.Add(ram);
}
}
Here is the screenshot with the results (as you can see, the first method is more precise):

Calculate pending time to finish processing threaded code C#

I have a code with threads and I want to show the pending time to finish processing. The button1 calls the
function "Function1()" that reads a file in chunks of 1024 bytes controlled in a while loop until get end
of file. Within the "While loop" there is a "foreach loop" where is called the "Function2()". I'm starting
the timer at the beginning of "while loop" and stopping it at the end of "while loop". After that I'm trying
to calculate aprox the Pending time knowing first the number of iterations that will be processed by "while loop".
Then I save the "elapsed time for the first iteration" (lets say T1) and then I multiply it by number of iterations.
This would be
PendingTime = T1*Iterations.
Then I do
PendingTime = PendingTime - Ti, where Ti is the ElapsedTime of the ith iteration.
The issue is when I try with the real code, the multiplation of T1*Iterations gives me 402s and actually
the processing takes 12s.
Maybe some expert could see what I'm doing wrong. Thanks in advance.
The code looks like this:
async void button1_Click(object sender, EventArgs e)
{
//Some code
await Task.Run(() => Function1(inputfile, cts.Token), cts.Token);
//Some code
}
public void Function2()
{
//Some code
}
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
decimal Iterations = 1;
int PendingTime = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length;
Iterations = (int)FileLength/buffer;
while (chunk.Length > 0)
{
Stopwatch sw1 = Stopwatch.StartNew(); //Start time counter
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//some code
chunk = reader.ReadBytes(buffer);
foreach (byte data in chunk)
{
//Some code
Function2(); //Call to Function2
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//Checking if it is the first iteration to save the pending time
//Pending time would be the elapsed time for the first iteration
//multiplied by the number of iterations (FileLength/1024).
sw1.Stop(); //Stop time counter
if (IterationCounter == 1)
{
PendingTime = (int)((decimal)Math.Round(sw1.Elapsed.TotalMilliseconds / 1000, 4)*Iterations);
}
//Show in TexBox1 the pending time
TextBox1.Invoke((MethodInvoker)delegate
{
PendingTime = PendingTime - (int)Math.Round(sw1.Elapsed.TotalMilliseconds / 1000, 4);
TextBox1.Text = PendingTime + " s";
});
}
}
}
Update:
I'm testing with the following code based on the example of Peter Duniho.
It can be tested with any file(i.e. txt file). I've tested with a txt file of 5MB and execution time was 3 seconds, but the pending time appear always as zero in TextBox1. Where I'm wrong?
Note: I changed this:
double timePerIteration = sw1.Elapsed / ++IterationCounter;
to this
double timePerIteration = sw1.ElapsedMilliseconds/1000/ ++IterationCounter;
Since I was getting the error:
Operator '/' cannot be applied to operands of type 'System.TimeSpan' and 'int' (CS0019)
The code so far is. Thanks for help.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestTimer
{
public partial class MainForm : Form
{
CancellationTokenSource cts = new CancellationTokenSource();
string filename = "";
long FileLength;
FileInfo fInfo;
Stopwatch sw1 = new Stopwatch();
public MainForm()
{
InitializeComponent();
}
void BtnSelectFileClick(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Title = "Select file";
DialogResult dr = ofd.ShowDialog();
if (dr == DialogResult.OK)
{
filename = ofd.FileName;
fInfo = new FileInfo(filename);
}
else
{
MessageBox.Show("File not found");
return;
}
}
async void BtnRunProcessClick(object sender, System.EventArgs e)
{
cts = new CancellationTokenSource();
await Task.Run(() => Function1(filename, cts.Token), cts.Token);
}
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
int Iterations = 0;
double pendingTime = 0;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
FileLength = (int)reader.BaseStream.Length;
Iterations = (int)FileLength/buffer;
byte[] chunk;
sw1 = Stopwatch.StartNew(); //Start time counter
while (true)
{
chunk = reader.ReadBytes(buffer);
if (chunk.Length == 0) {break;}
foreach (byte data in chunk)
{
Thread.Sleep(90/100);
}
// pendingTime is the current average time-per-iteration,
// times the number of iterations left
double timePerIteration = sw1.ElapsedMilliseconds/1000/ ++IterationCounter;
pendingTime = timePerIteration * (Iterations - IterationCounter);
TextBox1.Invoke((MethodInvoker)delegate
{
// Let string.Format() take care of rounding for you
TextBox1.Text = string.Format("{0:0} s", pendingTime / 1000);
});
}
MessageBox.Show("Execution time: " + string.Format("{0:0} s", sw1.ElapsedMilliseconds / 1000) );
}
}
}
}
I don't see how the code you posted ever actually compiled, never mind worked. The FileLength variable does not appear to be declared, and you never increment the IterationCounter variable, giving you a negative PendingTime value with each iteration. Even if you had incremented the counter, your PendingTime variable's actual meaning changes from the block that executes when the counter is 1 and a little later when you subtract your elapsed time from the current PendingTime variable.
That suggests the code you posted isn't really the code you're using, since the displayed time remaining would always have been negative (even assuming the declaration of FileLength just got accidently dropped from your post for some reason). For the sake of argument, I'll add a statement that does the increment…
As commenter Chris says, when each iteration's actual duration can vary, as it seems to be the case here, the best you're going to do is average all of the iterations up to the current one. Even that may lead to an erroneous time-remaining display, with a fair amount of variation from iteration to iteration (especially if the number of iterations is small), but at least it's more likely to be close.
Something like this would likely work better for you:
public void Function1(string inputfile, CancellationToken token)
{
int buffer = 1024;
int IterationCounter = 0;
int Iterations;
using (BinaryReader reader = new BinaryReader(File.Open(inputfile, FileMode.Open)))
{
if (reader.BaseStream.Length == 0)
{
// nothing to do
return;
}
// NOTE: this won't work for files with length > int.MaxValue!
// Your original code has the same limitation, and I have not
// bothered to change that.
// Now that we know for sure the length is > 0, we can
// do the following to ensure a correct iteration count
Iterations = ((int)reader.BaseStream.Length - 1) / buffer + 1;
Stopwatch sw1 = Stopwatch.StartNew();
while (chunk.Length > 0)
{
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//some code
chunk = reader.ReadBytes(buffer);
foreach (byte data in chunk)
{
//Some code
Function2(); //Call to Function2
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// pendingTime is the current average time-per-iteration,
// times the number of iterations left
double timePerIteration = sw1.ElapsedMilliseconds / ++IterationCounter,
pendingTime = timePerIteration *
(Iterations - IterationCounter);
//Show in TexBox1 the pending time
TextBox1.Invoke((MethodInvoker)delegate
{
// Let string.Format() take care of rounding for you
TextBox1.Text = string.Format("{0:0} s", pendingTime / 1000);
});
}
}
}
Unless you are guaranteed that your input file is always exactly a multiple of 1024 bytes in length, you also had a bug in your calculation of the total iteration count. I fixed that in the above as well.

More efficient way to calculate CPU Usage

So I'm writing a task manager clone, and right now I'm using this to calculate the CPU usage %s of each process. The problem is this is very slow; I was just wondering if there is a way to speed this up.
Also, I'm not allowed to use PerformanceCounter's methods and/or WMI.
//Omitted:
// - Process[] processes just holds the currently running processes
// - rows[] is a list of the rows I have in a table which shows the tables data
// - rows[2] is the column for CPU usage
// - rows[0] is the column for PID
//========
//Do CPU usages
double totalCPUTime = 0;
foreach (Process p in processes)
{
try
{
totalCPUTime += p.TotalProcessorTime.TotalMilliseconds;
}
catch (System.ComponentModel.Win32Exception e)
{
//Some processes do not give access rights to view their time.
}
}
foreach (Process p in processes)
{
double millis = 0;
try
{
millis = p.TotalProcessorTime.TotalMilliseconds;
}
catch (System.ComponentModel.Win32Exception e)
{
//Some processes do not give access rights to view their time.
}
double pct = 100 * millis / totalCPUTime;
for (int i = 0; i < rows.Count; i++)
{
if(rows[i].Cells[0].Value.Equals(p.Id))
{
rows[i].Cells[2].Value = pct;
break;
}
}
}
Use PerformanceCounter components to get different performance statistics:
var cpuCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName);
double value = cpuCounter.NextValue();
And here is sample of creating something like task manager.
Also consider using Win API function GetProcessTimes.

Categories