C# PerformanceMonitor only reports 0/100% with random, nonexistent spikes

此生再无相见时 提交于 2021-01-29 09:00:53

问题


I'm trying to make a sort of task manager -esque program using PerformanceMonitor and a chart. The CPU usage value is thrown onto a label and the chart, obviously, graphs it all out.

Problem is PerformanceMonitor only reports the CPU being at nothing or full, but the graph shows lots of little spikes in between, usually not matching the Windows Task Manager graph output.

I need to know how I can get PerformanceMonitor, or a similar C# product, to output viable, consistent, and accurate information into the graphing chart.

Code below. Timer interval is set to 25 for testing purposes currently.

public partial class formMain : Form
    {
        int usage;
        int x = 1;
        protected PerformanceCounter countCpu;

        public formMain()
        {
            InitializeComponent();
            myInit();
        }

        private void myInit()
        {
            countCpu = new PerformanceCounter("Processor", "% Processor Time", "_Total");

            timerMain.Tick += new EventHandler(timerMain_Tick);
            timerMain.Start();
        }

        private void timerMain_Tick(object sender, EventArgs e)
        {
            usage = Convert.ToInt32(countCpu.NextValue());
            chartCpu.Series["CPU"].Points.AddXY(x, usage);
            lblCpu.Text = Convert.ToString(usage.ToString()) + "%";
            x++;

            if(chartCpu.ChartAreas[0].AxisX.Maximum > chartCpu.ChartAreas[0].AxisX.ScaleView.Size)
            {
                chartCpu.ChartAreas[0].AxisX.ScaleView.Scroll(chartCpu.ChartAreas[0].AxisX.Maximum);
            }

        }
    }

Here's a screenshot detailing what I mean. Screenshot


回答1:


Your spiky graph is a standard mishap when you use that PerformanceCounter. A processor only has two states, running full bore as fast as it can or turned off completely when no work needs to be done. The perf counter tells you how often it was running vs how often it was turned off since you last called the NextValue() method.

If you do that too fast then the resolution suffers, you get too many samples that are 0, 33, 50, 67 or 100. Make it really short and you'll only ever get 0 or 100. So the primary diagnostic here is that your Timer.Interval is too short. You probably left it at the default, 100 msec. You need to make it 1000 to emulate the behavior of Task Manager or Performance Monitor.

Furthermore, on modern version of Windows you need to use a different PerformanceCounter to emulate what you get from the Windows utilities. That counter lives in the "Processor Information" category, still called "% Processor Time". It is a tweaked counter that better represents the amount of work a modern processor really does. Which is convoluted, modern processors dynamically adjust their clock frequency based on the chip temperature, so the amount of work they do is affected by what they've done before. And they emulate an extra core with hyper-threading. That extra logical core however cannot do as much work as a real core. The tweaked counter tries to compensate for these effects.




回答2:


It is because of your timer interval. Procesors don't have such a thing like CPU usage, they have CPU time (how much CPU spent time being active), so let's say your CPU time was 200 in now and will be 400 after a second, so (400 - 200) ms / 1000 ms * 100% equals 20 % CPU usage. Now lets say you need to calculate your CPU usage each 1 ms. Because CPU time is only integer, after that 1 ms you are trying to calculate, your CPU time will likely increase in 1 or even not increase at all. So (201 - 200) ms / 1 ms * 100% equals 100 %. The higher your interval is, the more accuracy you'll get in CPU usage calculation.




回答3:


Managed to accidentally fix this by removing the myInit method and adjusting the code.

Final code:

public partial class formMain : Form
    {
        int usage;
        int x = 1;
        protected PerformanceCounter countCpu = new PerformanceCounter("Processor", "% Processor Time", "_Total");

        public formMain()
        {
            InitializeComponent();

            timerMain.Tick += new EventHandler(timerMain_Tick);
            timerMain.Start();
        }

        private void timerMain_Tick(object sender, EventArgs e)
        {
            usage = Convert.ToInt32(countCpu.NextValue());
            chartCpu.Series["CPU"].Points.AddXY(x, usage);
            lblCpu.Text = Convert.ToString(usage.ToString()) + "%";
            x++;

            if(chartCpu.ChartAreas[0].AxisX.Maximum > chartCpu.ChartAreas[0].AxisX.ScaleView.Size)
            {
                chartCpu.ChartAreas[0].AxisX.ScaleView.Scroll(chartCpu.ChartAreas[0].AxisX.Maximum);
            }
        }
    }


来源:https://stackoverflow.com/questions/24838769/c-sharp-performancemonitor-only-reports-0-100-with-random-nonexistent-spikes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!