1

Im currently developing something to track CPU usage but as soon as i started the thread that pulls the data from the CPU the screen went blank as if i started a fresh program.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Management.Instrumentation;
using System.Management;
using System.Collections.Specialized;

namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
    Thread cpuData;
    public Form1()
    {

        cpuData = new Thread(new ThreadStart(cpuDataThread));
        cpuData.Start();
    }
    public void cpuDataThread()
    {
        ulong i;
        i = 0;
        try
        {
            ManagementClass cpuDataClass = new ManagementClass("Win32_PerfFormattedData_PerfOS_Processor");

            while (true)
            {
                ManagementObjectCollection cpuDataClassCollection = cpuDataClass.GetInstances();
                foreach (ManagementObject obj in cpuDataClassCollection)
                {
                    if (obj["Name"].ToString() == "_Total")
                    {
                        i = Convert.ToUInt64(obj["C1TransitionsPersec"]);
                    }
                }
                Thread.Sleep(100);
            }
        }
        catch (ThreadAbortException tbe)
        {

        }
        progressBar1.Maximum = 100;
        progressBar1.Minimum = 1;

        progressBar1.Value = (int)i;
    }
}
}

This is just a program i wrote for personal usage but id like to get it working, the progress bar also does not work id like to get some help with that as well.

  • 1
    Can you clarify what you mean by blank? The program disappears completely, goes white as if the UI thread is locked, or looks like you have no controls of the form? I can't see where you break out of your while loop, is it meant to run forever like that? – Equalsk Jul 21 '15 at 13:15
  • Yea and this loop. Haven't notice it – MajkeloDev Jul 21 '15 at 13:16
  • Its ment to run forever it is supposed to fetch the cpu usage every .1 second and its exacly looking like u started a new project and run it without modifying it first – Project RedLow Jul 21 '15 at 13:23
  • So just to be 100%, you're saying if you comment out the line to start the thread like this `//cpuData.Start();` that the program looks fine and has all of your controls on like the progress bar. If you then start the thread all of those things disappear and it looks like a brand new empty form? – Equalsk Jul 21 '15 at 13:25
  • It was doing that before yes – Project RedLow Jul 21 '15 at 13:28
  • 1
    Your code is poorly structured. It will only ever update the screen once (or attempt to and fail) but only if an exception is thrown to break the infinite loop. It's quite back-to-front –  Jul 21 '15 at 13:46
  • I reprogrammed it from a program that Barnacules Nerdgasm wrote wich worked when he made it i just wanted to adapt it for cpu usage and ram usage and so far i couldnt even get the cpu usage working – Project RedLow Jul 21 '15 at 13:48

3 Answers3

1

Your constructor isn't calling InitializeComponent() which is the method that is created by the WinForms designer.

Ed T
  • 410
  • 4
  • 11
0

You probably also need to provide following properties to Your Thread(Before Start Method):

cpuData.SetApartmentState(ApartmentState.STA);
cpuData.IsBackground = true;

And following Your second problem(progressbar). If You want to pass data to UI You need to use Dispatcher, like below:

Dispatcher.Invoke((Action)delegate() { /* update UI */ });
MajkeloDev
  • 1,661
  • 13
  • 30
  • That crashes the minute i close the window+ it doesn`t solve it – Project RedLow Jul 21 '15 at 13:12
  • It's crashing because You are trying to call UI from second Thread without usign Dispatcher. – MajkeloDev Jul 21 '15 at 13:15
  • And like @Equalsk said - You created an infinite loop. – MajkeloDev Jul 21 '15 at 13:17
  • An infinite loop isn't technically bad, it's a common way to keep a thread alive which is what I assume he's doing, but I want to check since they're a common cause of deadlock. – Equalsk Jul 21 '15 at 13:18
  • Where would i need to place that dispatcher.Invoke line? im really new to c# this is actually my first proper program – Project RedLow Jul 21 '15 at 13:21
  • 1
    I'd use a `Background worker`, set its `Reports progess` property to true and put the progressbar update in the ProgessChanged event – LocEngineer Jul 21 '15 at 13:23
  • This is all academic, the infinite `while` loop prevents updates to the progressBar, thread-marshalled or not –  Jul 21 '15 at 13:48
  • @ProjectRedLow Use Dispatcher to update progress bar so instead of "progressBar1.Value" do this inside Dispatcher Clause – MajkeloDev Jul 22 '15 at 07:05
0

I've tinkered a bit around with your code, seems to work:

You are using Win forms, so have I. Instead of manually threading I have used a Backgroundworker ("bkwCpuLoad").

To accomodate for the values, I have set the max to 10,000:

private void Form1_Load(object sender, EventArgs e)
{
    progressBar1.Maximum = 10000;
    progressBar1.Minimum = 0;
    bkwCpuLoad.RunWorkerAsync();
}

private void bkwCpuLoad_DoWork(object sender, DoWorkEventArgs e)
{
    ulong i;
    i = 0;
    try
    {
        ManagementClass cpuDataClass = new ManagementClass("Win32_PerfFormattedData_PerfOS_Processor");

        while (true)
        {
            ManagementObjectCollection cpuDataClassCollection = cpuDataClass.GetInstances();
            foreach (ManagementObject obj in cpuDataClassCollection)
            {
                if (obj["Name"].ToString() == "_Total")
                {
                    i = Convert.ToUInt64(obj["C1TransitionsPersec"]);
                }
                bkwCpuLoad.ReportProgress((int)i);
            }
            Thread.Sleep(100);
        }
    }
    catch (ThreadAbortException tbe)
    {

    }
}

private void bkwCpuLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    var perc = e.ProgressPercentage;
    if (perc > progressBar1.Maximum)
        perc = progressBar1.Maximum;
    progressBar1.Value = perc;
    try
    {
        progressBar1.Value--;
        progressBar1.Value++;
    }
    catch
    {
    }
}

Exaplanation for the progressBar1.Value--, progressBar1.Value++ bit: One thing that is anything but ideal in a case like yours is the progressbar animation, which is too slow. But: if you reduce a progressbar value, it is not animated but painted directly. Therefore, settings the value (animation starts), reducing it by 1 (jumps directly to value) the increasing it again makes your progressbar essentially faster. ;-)

LocEngineer
  • 2,847
  • 1
  • 16
  • 28
  • Don't forget to mention that to use this sample you'll need to drag a `BackGroundWorker` from the `Components` part of the `ToolBox` onto your project. OP should see the [MSDN documentation](https://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx) on using backgroundworkers for more information. – Equalsk Jul 21 '15 at 13:59
  • That seems to work but i cant get the cpu utilization data to show up, do i need to start that script in any way? – Project RedLow Jul 21 '15 at 14:04
  • What exactly do you wish to show up at what point in time and where on the form? – LocEngineer Jul 21 '15 at 14:07
  • Basically real time cpu load and in the future ram load – Project RedLow Jul 21 '15 at 14:09
  • For CPU Load you'll probably need `PercentProcessorTime` instead of `C1TransitionsPersec`. Take a look here: http://www.codeproject.com/Articles/42580/find-out-how-processor-load-using-wmi. Also check out this: http://stackoverflow.com/questions/2342023/how-to-measure-the-total-memory-consumption-of-the-current-process-programatical?lq=1 and this: http://stackoverflow.com/questions/4679962/what-is-the-correct-performance-counter-to-get-cpu-and-memory-usage-of-a-process?rq=1 – LocEngineer Jul 21 '15 at 14:17