Display CPU usage of all running processes, programmatically? - c#

Question
How do I get the cpu usage of each process into PopulateApplications()?
What's happening
getCPUUsage() gives me the same value for each process. It's like it's getting the cpu usage for only one process.
The rest of the code seems to work fine.
getCPUUsage() from class Core:
public static double getCPUUsage()
{
ManagementObject processor = new ManagementObject("Win32_PerfFormattedData_PerfOS_Processor.Name='_Total'");
processor.Get();
return double.Parse(processor.Properties["PercentProcessorTime"].Value.ToString());
}
What I've tried
In form1, I have a method by which I display information about processes like icons, name, and statuses (i.e. running/not running).
void PopulateApplications()
{
DoubleBufferedd(dataGridView1, true);
int rcount = dataGridView1.Rows.Count;
int rcurIndex = 0;
foreach (Process p in Process.GetProcesses())
{
try
{
if (File.Exists(p.MainModule.FileName))
{
var icon = Icon.ExtractAssociatedIcon(p.MainModule.FileName);
Image ima = icon.ToBitmap();
ima = resizeImage(ima, new Size(25, 25));
ima = (Image)(new Bitmap(ima, new Size(25, 25)));
String status = p.Responding ? "Running" : "Not Responding";
if (rcurIndex < rcount - 1)
{
var currentRow = dataGridView1.Rows[rcurIndex];
currentRow.Cells[0].Value = ima;
currentRow.Cells[1].Value = p.ProcessName;
currentRow.Cells[2].Value = cpuusage;
currentRow.Cells[3].Value = status;
}
else
{
dataGridView1.Rows.Add(
ima, p.ProcessName,cpuusage, status);//false, ima, p.ProcessName, status);
}
rcurIndex++;
}
}
catch ( Exception e)
{
string t = "error";
}
}
if (rcurIndex < rcount - 1)
{
for (int i = rcurIndex; i < rcount - 1; i++)
{
dataGridView1.Rows.RemoveAt(rcurIndex);
}
}
}
I added this line:
currentRow.Cells[2].Value = cpuusage;
cpuusage is double-type variable.
I changed this line, also, to include addition of cpuusage:
dataGridView1.Rows.Add(
ima, p.ProcessName,cpuusage, status);
Now I have a background worker event, dowork, whereby I use cpuusage to get the cpu usage values:
this.Invoke(new Action(() => cpuusage = Core.getCPUUsage()));
Maybe I don't need to call the method getCPUUsage() through backgroundworker.
This is what i see when im running the program:
All the processes have the same cpu usage ? Not logic.
Then when there is an update i see:
Again all the cells have the same cpu usage value. But on the left there are many processes each should have it's own cpu usage.

Related

C# Console App Suspends Sporadically After a While?

I have a C# console app that is processing huge data in a Parallel.For loop.
But after a while my app suspends periodically(CPU-Usage falls down ),exactly in the same For-loop with same process.
CPU doesn't do anything on my app based on profiling information.
I guess it may be related to memory because it happens when memory usage reaches above 90%.
Thank you for your help.
Image of CPU usage profiling when Main is Selected
feasiblePairs22222 = new List<Pair>();
Pair[] tempPair = new Pair[tripListSize];
Parallel.For(0, tripListSize, tri=> {
var PairingStack = new Stack<List<Trip>>();
var firstElement = new List<Trip>();
firstElement.Add(Program.tripList[tri]);
PairingStack.Push(firstElement);
while (PairingStack.Count > 0)
{
var tempPairing11 = PairingStack.Pop();
int start = tempPairing11[tempPairing11.Count - 1].index;
int startTime = tempPairing11[0].departureTime;
foreach (Trip candidToAdd in twoTripMatchable[start])
{
if (candidToAdd.araivalTime - startTime > Program.WorkingTimeLimit) { continue; }
if (candidToAdd.departureTime - tempPairing11[tempPairing11.Count - 1].araivalTime > 30) { continue; }
var newPairing = new List<Trip>();
newPairing.AddRange(tempPairing11);
newPairing.Add(candidToAdd);
PairingStack.Push(newPairing);
int workingTime = 0;
foreach (Trip currentTrip in newPairing) { workingTime = workingTime + currentTrip.Duration; }
if (workingTime <= 180) { continue; }
newPairing.ForEach(o => o.isCovered++);
lock (tempPair)
{
tempPair[tri] = new Pair();
tempPair[tri].PairTrips = newPairing.ToArray();
feasiblePairs22222.Add(tempPair[tri]);
}
}
}
});

Change colors in a datagridview depending on the process tree

I know how to change the colors of a "Row" in a DataGridView, my difficulty is that, I have to list all the processes that are running (done), but I need to put a different foreground color for each process tree and without repeting any process on the list, this became quite complicated for me as a beginner, the only thing I found was a method that made my program extremely slow here in the stackoverflow, if there is any more optimized method I would appreciate it.
Here's my old code that only get ths list of processes:
private void getProcessList ()
{
Process [] processesList = Process.GetProcesses ();
foreach (Process process in processesList)
{
double memory = float.Parse (ConvertBytesToMegabytes (process.PrivateMemorySize64) .ToString ());
memory = Math.Round (memory, 2);
string processState = "";
if (process.Responding == true)
stateProc = "Active";
else
stateProc = "Does not answer";
dataGridView1.Rows.Add (process.ProcessName, processState, process.Id, memory + "MB", process.Threads.Count, btnFinalizarProc);
}
totalProc = processesList.Length;
}
Since the definition of btnFinalizarProc is missing in your code, I have omitted the btnFinalizarProc column in the DataGridView.
You can try to use Color.FromArgb() and Random to generate random colors.
And then define a dictionary to store Name_Color key-value pairs
Here is a demo you can refer to.
Dictionary<string, Color> name_color = new Dictionary<string, Color>();
private void getProcessList()
{
Random random = new Random();
Process[] processesList = Process.GetProcesses();
foreach (Process process in processesList)
{
double memory = float.Parse(ConvertBytesToMegabytes(process.PrivateMemorySize64).ToString());
memory = Math.Round(memory, 2);
string processState = "";
if (process.Responding == true)
processState = "Active";
else
processState = "Does not answer";
// Check if contains
if (!name_color.ContainsKey(process.ProcessName))
{
int int_Red = random.Next(256);
int int_Green = random.Next(256);
int int_Blue = random.Next(256);
Color color = Color.FromArgb(int_Red, int_Green, int_Blue);
name_color.Add(process.ProcessName, color);
}
DataGridViewRow row = (DataGridViewRow)dataGridView1.Rows[0].Clone();
row.Cells[0].Value = process.ProcessName;
row.Cells[1].Value = processState;
row.Cells[2].Value = process.Id;
row.Cells[3].Value = memory + "MB";
row.Cells[4].Value = process.Threads.Count;
row.DefaultCellStyle.ForeColor = name_color[process.ProcessName];
dataGridView1.Rows.Add(row);
}
}
private void button1_Click(object sender, EventArgs e)
{
getProcessList();
}
Test result,

Waiting for a parse.com async task to finish in Unity3D

As part of my school project I'm trying to link two tables to decrease the amount of data stored in one table so I wanted to link my "Scores" class with my "CorrectAnswers" class via the ObjectID. However since the tasks are asynchronous, by the time one task is done saving, the other task has already begun or also finished saving and so the ObjectID returns as null.
Here's the code I'm using:
public void SaveScore()
{
ParseObject SendScore = new ParseObject("Scores");
SendScore["Score"] = CheckAnswer.score;
SendScore["user"] = ParseObject.CreateWithoutData("_User", ParseUser.CurrentUser.ObjectId);
SendScore["TestMode"] = MainMenu.testmode;
SendScore["TotalQuestions"] = QuestionCreation.TotalQuestions;
SendScore["CorrectQuestions"] = CheckAnswer.CorrectQuestions;
SendScore.SaveAsync().ContinueWith(t =>
{
ScoreObjectId = SendScore.ObjectId;
});
ParseObject SendCorrectTopics = new ParseObject("CorrectAnswers");
SendCorrectTopics["Score"] = SendScore.ObjectId;
for (int i = 0; i <= 9; i++)
{
string Topic = "Topic" + (i + 1).ToString();
SendCorrectTopics[Topic] = CheckAnswer.CorrectTopics[i];
}
SendCorrectTopics.SaveAsync();
SceneManager.LoadScene(0);
}
How would I be able to make the second save hold until the first save has finished? I'm somewhat new to C# and so don't quite know all it's features yet. I've looked into "await" but unity doesn't seem to like that. Any help would be greatly appreciated!
Thanks in advance,
EDIT: Okay, after a bit more reading on Unity's coroutines, I found a much better way of checking that only relies on checking when needed:
IEnumerator CheckSave()
{
while(ScoreObjectId == null & !DoneSave))
{
print("Running");
yield return new WaitForSeconds(0.5f);
}
DoneSave = false;
SaveTotalTopics();
}
This seems like a much better way of doing it.
Well, it seems the answer was something I've already done before, even if it is a little ugly.
Using Unity's update function I created a check to make sure the ObjectID is not null and the previous save had completed, as so:
void Update () {
if (ScoreObjectId != null & DoneSave)
{
DoneSave = false;
SaveTotalTopics();
}
Thus splitting it into two saves and creating:
public void SaveScore()
{
ParseObject SendScore = new ParseObject("Scores");
SendScore["Score"] = CheckAnswer.score;
SendScore["user"] = ParseObject.CreateWithoutData("_User", ParseUser.CurrentUser.ObjectId);
SendScore["TestMode"] = MainMenu.testmode;
SendScore["TotalQuestions"] = QuestionCreation.TotalQuestions;
SendScore["CorrectQuestions"] = CheckAnswer.CorrectQuestions;
Task SendingScores = SendScore.SaveAsync().ContinueWith(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
DoneSave = false;
print(t.Exception);
}
else
{
DoneSave = true;
print("Setting object ID!");
ScoreObjectId = SendScore.ObjectId;
print(ScoreObjectId);
}
});
}
void SaveTotalTopics()
{
for (int i = 0; i <= 9; i++)
{
string Topic = "Topic" + (i + 1).ToString();
SendCorrectTopics[Topic] = CheckAnswer.CorrectTopics[i];
}
SendCorrectTopics["UserScore"] = ParseObject.CreateWithoutData("Scores", ScoreObjectId);
SendCorrectTopics.SaveAsync().ContinueWith(t =>
{
if(t.IsFaulted || t.IsCanceled)
{
print(t.Exception);
}
else
{
print("Saved!");
}
});
}
I'd also forgotten to use ParseObject.CreateWithoutData() so my first code snippet wouldn't have worked even if I'd found a better method...
So, although I'm not happy with the final result, at least it works and I don't think running an if statement every frame should significantly impact on my game's performance.
Why not use a bool and a while loop?
public IEnumerator SaveScore()
{
bool canContinue = false;
ParseObject SendScore = new ParseObject("Scores");
SendScore["Score"] = CheckAnswer.score;
SendScore["user"] = ParseObject.CreateWithoutData("_User", ParseUser.CurrentUser.ObjectId);
SendScore["TestMode"] = MainMenu.testmode;
SendScore["TotalQuestions"] = QuestionCreation.TotalQuestions;
SendScore["CorrectQuestions"] = CheckAnswer.CorrectQuestions;
SendScore.SaveAsync().ContinueWith(t =>
{
ScoreObjectId = SendScore.ObjectId;
//set the bool canContinue to true because the first portion of code has finished running
canContinue = true;
});
//wait while the canContinue bool is false
while(!canContinue){
yield return null;
}
//continue your parse code
ParseObject SendCorrectTopics = new ParseObject("CorrectAnswers");
SendCorrectTopics["Score"] = SendScore.ObjectId;
for (int i = 0; i <= 9; i++)
{
string Topic = "Topic" + (i + 1).ToString();
SendCorrectTopics[Topic] = CheckAnswer.CorrectTopics[i];
}
SendCorrectTopics.SaveAsync();
SceneManager.LoadScene(0);
return null;
}

Using ParallelFor to change listview

I have a function which modifies my listview "inputList",the listview has 5 columns. The function is supposed to check the cells in the listview,the cells in the last column will have "NORMAL" with green background if there is nothing wrong and if there is something wrong, it will have "ERROR" with red background in the cell in the last column and also change the color of the cells that are wrong in the same line from the other columns.
There are 4k items, I know that it's pointless to have so many item since the user is not going to read them but I was asked to this way.
I'm using a function with backgroundworker but its not fast enough and thought parallelFor would be faster. But when I try the parallelFor, its freezing the program.
This is the function with backgroundworker which is working but its too slow:
private void bw3_DoWork(object sender, DoWorkEventArgs e)
{
String tempTrain = "";
String tempPredic = "";
String tempNet = "";
Boolean bTrain;
Boolean bPredic;
Boolean bNetErro;
int n;
int nNet = 0;
String tTrain = "";
String tPredic = "";
int nList = 0;
this.Invoke(new MethodInvoker(() => {
nList = inputList.Items.Count;
nNet = menuNetwork.Items.Count;
tTrain = dtrainTextBox.Text;
tPredic = dpredicTextBox.Text;
}));
for (int i = 0; i < nList; i++)
{
ListViewItem.ListViewSubItem temp1 = new ListViewItem.ListViewSubItem();
temp1.BackColor = Color.LightGreen;
temp1.Text = "NORMAL";
this.Invoke(new MethodInvoker(() =>
{
inputList.Items[i].SubItems[0].BackColor = Color.White;
inputList.Items[i].SubItems[1].BackColor = Color.White;
inputList.Items[i].SubItems[2].BackColor = Color.White;
tempTrain = String.Format("{0}\\{1}", tTrain, inputList.Items[i].SubItems[1].Text);
tempPredic = String.Format("{0}\\{1}", tPredic, inputList.Items[i].SubItems[2].Text);
tempNet = (String)inputList.Items[i].SubItems[0].Tag;
}));
bTrain = (!File.Exists(tempTrain));
bPredic = (!File.Exists(tempPredic));
bNetErro = !(int.TryParse(tempNet, out n));
if (!bNetErro)
{
if (!(n < nNet))
{
bNetErro = true;
}
}
this.Invoke(new MethodInvoker(delegate
{
if (bTrain) inputList.Items[i].SubItems[1].BackColor = Color.Red;
if (bPredic) inputList.Items[i].SubItems[2].BackColor = Color.Red;
if (bNetErro) inputList.Items[i].SubItems[0].BackColor = Color.Red;
if (bTrain | bPredic | bNetErro) { temp1.Text = "Erro"; temp1.BackColor = Color.Red; }
try { inputList.Items[i].SubItems[4] = temp1; }
catch (ArgumentOutOfRangeException) { inputList.Items[i].SubItems.Add(temp1); }
}));
}
}
And this is the function with ParallelFor, the program stops working even when I try a very small example with only items.
private void tent1()
{
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = 4;
String tempTrain = "";
String tempPredic = "";
String tempNet = "";
String tTrain = dtrainTextBox.Text;
String tPredic = dpredicTextBox.Text;
Boolean bTrain;
Boolean bPredic;
Boolean bNetErro;
int n;
int nNet = networkList.Items.Count;
Parallel.For(0, inputList.Items.Count,
i =>
{
ListViewItem.ListViewSubItem temp1 = new ListViewItem.ListViewSubItem();
temp1.BackColor = Color.LightGreen;
temp1.Text = "NORMAL";
Console.WriteLine(i);
this.Invoke(new MethodInvoker(() =>
{
inputList.Items[i].SubItems[0].BackColor = Color.White;
inputList.Items[i].SubItems[1].BackColor = Color.White;
inputList.Items[i].SubItems[2].BackColor = Color.White;
tempTrain = String.Format("{0}\\{1}", tTrain, inputList.Items[i].SubItems[1].Text);
tempPredic = String.Format("{0}\\{1}", tPredic , inputList.Items[i].SubItems[2].Text);
tempNet = (String)inputList.Items[i].SubItems[0].Tag;
}));
bTrain = (!File.Exists(tempTrain));
bPredic = (!File.Exists(tempPredic));
bNetErro = !(int.TryParse(tempNet, out n));
if (!bNetErro)
{
if (!(n < nNet))
{
bNetErro = true;
}
}
this.Invoke(new MethodInvoker(delegate
{
if (bTrain) inputList.Items[i].SubItems[1].BackColor = Color.Red;
if (bPredic) inputList.Items[i].SubItems[2].BackColor = Color.Red;
if (bNetErro) inputList.Items[i].SubItems[0].BackColor = Color.Red;
if (bTrain | bPredic | bNetErro) { temp1.Text = "Erro"; temp1.BackColor = Color.Red; }
try { inputList.Items[i].SubItems[4] = temp1; }
catch (ArgumentOutOfRangeException) { inputList.Items[i].SubItems.Add(temp1); }
}));
});
}
How can I copy all items of the listview to a List without reference? I think adding/modify directly into the listview and the invokes are slowing the function so creating: List<ListViewItem> tList
I would modify everything in the tList and then I would use inputList.Items.AddRange(tList.ToArray());
This would remove all the invokes inside the loop.
ListViewItem[] tItemsTemp = null;
this.Invoke(new MethodInvoker(() =>
{
tItemsTemp = new ListViewItem[inputList.Items.Count];
inputList.Items.CopyTo(tItemsTemp, 0);
nList = inputList.Items.Count;
nNet = menuNetwork.Items.Count;
tTrain = dtrainTextBox.Text;
tPredic = dpredicTextBox.Text;
}));
List<ListViewItem> tList = new List<ListViewItem>(tItemsTemp);
ListViewItem[] tItems = (ListViewItem[]) tItemsTemp.Clone();
//Modifies the list or array of listviewitems
this.Invoke(new MethodInvoker(delegate
{
inputList.Items.Clear();
// Just one of them,not the 3,just showing how i would call them.
inputList.Items.AddRange(tItems);
inputList.Items.AddRange(tItemsTemp);
inputList.Items.AddRange(tList.ToArray());
}));
But tItemsTemp,tItems,tList were all references...
How can I copy with creating a reference?
Mixing UI and parallelization is not guaranteed to provide good results. The UI is a bottleneck by itself because it runs on a unique thread. Worse, yours includes some disk IO operations (File.Exists).
There are some things you may want to try anyway:
Enclose the whole loop with an inputList.BeginUpdate and an inputList.EndUpdate. This prevents the list to refresh each time you add an item.
Try SynchronizationContext and the Post method instead of the old fashioned Invoke. This might make the UI invocation smoother. See this answer to check how it works.
By the way, you can remove the first Invoke, if it is possible for you to move the three lines that ends with .backcolor = Color.White in the second Invoke.
If it is not better, then try to separate the process of building the items and displaying them :
Use parallelization fill a List of items to update (not with a ForEach, but with .AsParallel() against a LINQ query)
Use a loop to update your ListView.
If this is not satisfying, you will probably have to find a workaround using a ListView in virtual mode. This answer gives some hints to fill a virtual ListView an asynchronous way.

Task Parallel Library - I don't understand what I'm doing wrong

This is a two part question.
I have a class that gets all processes asynchronously and polls them for CPU usage. Yesterday I had a bug with it and it was solved here.
The first part of the question is why the solution helped. I didn't understand the explanation.
The second part of the question is that I still get an "Object reference not set to an instance of object" exception occasionally when I try to print the result at the end of the process. This is because item.Key is indeed null. I don't understand why that is because I put a breakpoint checking for (process == null) and it was never hit. What am I doing wrong?
Code is below.
class ProcessCpuUsageGetter
{
private IDictionary<Process, int> _usage;
public IDictionary<Process, int> Usage { get { return _usage; } }
public ProcessCpuUsageGetter()
{
while (true)
{
Process[] processes = Process.GetProcesses();
int processCount = processes.Count();
Task[] tasks = new Task[processCount];
_usage = new Dictionary<Process, int>();
for (int i = 0; i < processCount; i++)
{
var localI = i;
var localProcess = processes[localI];
tasks[localI] = Task.Factory.StartNew(() => DoWork(localProcess));
}
Task.WaitAll(tasks);
foreach (var item in Usage)
{
Console.WriteLine("{0} - {1}%", item.Key.ProcessName, item.Value);
}
}
}
private void DoWork(object o)
{
Process process = (Process)o;
PerformanceCounter pc = new PerformanceCounter("Process", "% Processor Time", process.ProcessName, true);
pc.NextValue();
Thread.Sleep(1000);
int cpuPercent = (int)pc.NextValue() / Environment.ProcessorCount;
if (process == null)
{
var x = 5;
}
if (_usage == null)
{
var t = 6;
}
_usage.Add(process, cpuPercent);
}
}
The line
_usage.Add(process, cpuPercent);
is accessing a not-threadsafe collection from a thread.
Use a ConcurrentDictionary<K,V> instead of the normal dictionary.
The 'null reference' error is just a random symptom, you could get other errors too.

Categories