10

This is what im doing in form1:

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))
            {
                memoryUsage = Core.getallmemoryusage(p.ProcessName);
                Core.getcpu(p.ProcessName);
                cpuusage = Core.processes;

                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 = memoryUsage;
                    currentRow.Cells[4].Value = status;
                }
                else
                {
                    dataGridView1.Rows.Add(ima, p.ProcessName,cpuusage,memoryUsage, 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);
        }
    }
}

Now the method in form1 PopulateApplications, I call it from a timer tick event each 5 seconds. Then I loop each time over the processes and get the memory usage and CPU usage. This are the methods of memory and CPU in the class Core.

With the memory method there is no problems. Working good and fast.

public static string getallmemoryusage(string processName)
{
    var counter = new PerformanceCounter("Process", "Working Set - Private", processName);
    privateMemeory = (counter.NextValue() / 1024 / 1024).ToString();
    //string.Format("Private memory: {0}k", counter.NextValue() / 1024 / 1024);
    return privateMemeory;           
}

The problem is with the getcpu method. I need to make it sleep every 1000ms few times to get the CPU usage. If I use a breakpoint on this method, I will get the value in the end. The problem is when I call the method in form1 each 5 seconds it's also calling and doing this getcpu every 5 seconds and those threads sleep make it work very slow. If I will set the threads sleep to 10ms it will be faster but then I get on most processes 0% or 100% usage.

public static string  getcpu(string name)
{
    var cpuload = new PerformanceCounter("Processor", "% Processor Time", "_Total");

    processes = Convert.ToInt32(cpuload.NextValue()) + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    processes = cpuload.NextValue() + "%";
    System.Threading.Thread.Sleep(1000);

    return processes;
}
Abbas
  • 14,186
  • 6
  • 41
  • 72
user3681442
  • 297
  • 3
  • 15
  • Rotem right i changed my question with updated getcpu method using the name variable and im not itertiing on all the processes again only in form1 once. Still i get 0% on every process. For example in test List i see 1 index and: chorme CPU0% and the same for every process. – user3681442 Jun 09 '14 at 15:35
  • In the getcpu method i don't get exception i added try and catch now no exceptions. But in form1 it throw sometimes exceptions on some processes access denied but those are system processes so i don't mind they get access denied. – user3681442 Jun 09 '14 at 15:39
  • I just updated my question again showing the memory usage part is working no problems. Still the cpu usage not working. – user3681442 Jun 09 '14 at 15:43
  • Updated my question again with what i tried now in the bottom of the question. Tried another solution but it's not working either. Tried this solution: http://stackoverflow.com/questions/2181828/why-the-cpu-performance-counter-kept-reporting-0-cpu-usage but how do i use and where now with the process name in the method getcpu ? ( variable name) – user3681442 Jun 09 '14 at 16:08
  • Apart from the fact that you need to divide your results by the number of processors, (ie System.Environment.ProcessorCount), I don't see anything wrong with your code and it works for me. What happens if you try to get the % idle time (ie pass in "Idle" as the third parameter instead of processor name, or "_Total") – sgmoore Jun 09 '14 at 17:13
  • sgmoore the problem in my code is that the method in form1 is under 5 seconds timer tick event. So i call the getgpu() method each time again every 5 seconds and since the thread sleep is set to 1000 it will take forever each time to do it. I will exaplin with the code in form1 in my question since im adding the cpu usage values to dataGridView1. – user3681442 Jun 09 '14 at 17:21
  • sgmoore look please on my question now. Updated it explained the problem. – user3681442 Jun 09 '14 at 17:31

1 Answers1

7

When measuring % Processor Time, the Thread.Sleep(1000) is required since the .NextValue() call determines the time, the processor was used since the last call to .NextValue(). For further information on this calculation, check out https://learn.microsoft.com/en-us/archive/blogs/bclteam/how-to-read-performance-counters-ryan-byington.

A couple of suggestions:

  1. Since you are passing in the name of a process, I assume you want to measure the Processor Time of a single process. But as you are not using that parameter within your method, you are measuring the overall average system processor time instead.

So if you want to measure the performance for one single process, you could use something like:

public static double GetCpuUsage(Process process)
{
    PerformanceCounter cpuCounter = new PerformanceCounter();

    cpuCounter.CategoryName = "Process";
    cpuCounter.InstanceName = process.ProcessName;
    cpuCounter.CounterName = "% Processor Time";

    // The first call will always return 0
    cpuCounter.NextValue();
    // That's why we need to sleep 1 second 
    Thread.Sleep(1000);
    // The second call determines, the % of time that the monitored process uses on 
    // % User time for a single processor. 
    // So the limit is 100% * the number of processors you have.
    double processorUsagePercent = cpuCounter.NextValue();

    // Hence we need to divide by the number of processors to get the average CPU usage of one process during the time measured
    return processorUsagePercent / Environment.ProcessorCount;
}

Please mind the difference between "Processor" and "Process" for the counter category.

  1. Why are you calling .NextValue() multiple times in a row and then return only the last value? That makes your method so slow. The two calculations shown in the example above are sufficient.

  2. When you want to monitor multiple processes, you do not have to wait one second in between every call to .NextValue(). You just have to make sure that at least one second has elapsed since the last time you called .NextValue() on a specific counter. So for multiple processes you could have a method like that:

    public static Dictionary<Process, double> GetCpuUsages(Process[] processes) { // One performance counter is required per process PerformanceCounter[] counters = new PerformanceCounter[processes.Length];

     // Instantiate a new counter per process
     for(int i = 0; i < processes.Length; i++)
     {
         PerformanceCounter processorTimeCounter = new PerformanceCounter(
             "Process",
             "% Processor Time",
             processes[i].ProcessName);
         // Call NextValue once to have a reference value
         processorTimeCounter.NextValue();
         // Add it to the array
         counters[i] = processorTimeCounter;
     }
    
     // Sleep one second to have accurate measurement
     Thread.Sleep(1000); 
     // Here we store the processes along with their measurement in a dictionary
     Dictionary<Process, double> cpuUsageDictionary = new Dictionary<Process, double>();
    
     for (int i = 0; i < counters.Length; i++)
     {
         // Determine CPU usage and divide by the number of cores
         double cpuUsage = counters[i].NextValue() / Environment.ProcessorCount;
         // And now we add one key/value pair per process along with its cpu time measurement
         cpuUsageDictionary.Add(processes[i],  cpuUsage);
     }
    
     return cpuUsageDictionary;
    

    }

Michel de Ruiter
  • 7,131
  • 5
  • 49
  • 74
Ben Sch
  • 2,909
  • 4
  • 20
  • 23