I've been attempting to implement a CPU monitor that updates every two seconds and displays it on a label called "cpu_usage" in WinForms. Unfortunately my code does not appear to work and gives off this error during runtime:
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'cpu_usage' accessed from a thread other than the thread it was created on.'
So far I've done a little bit of debugging, and have out that the error occurs whenever I try to display the percentage on the "cpu-usage" label, but I am still unable to figure out how to fix this issue. The CPU monitoring code is below:
public my_form()
{
InitializeComponent();
// Loads the CPU monitor
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
InitTimer();
}
// Timer for the CPU percentage check routine
public void InitTimer()
{
cpu_timer = new Timer();
cpu_timer.Elapsed = new ElapsedEventHandler(cpu_timer_Tick);
cpu_timer.Interval = 2000;
cpu_timer.Start();
}
// Initates the checking routine
private void cpu_timer_Tick(object sender, EventArgs e)
{
cpu_usage.Text = getCurrentCpuUsage(); // This line causes the exception error.
}
// Method to find the CPU resources
public string getCurrentCpuUsage()
{
string value1 = (int)cpuCounter.NextValue() "%";
Thread.Sleep(500);
string value2 = (int)cpuCounter.NextValue() "%";
return value2.ToString();
}
CodePudding user response:
I managed to fix this error by using System.Windows.Forms
for the timer, instead of using the System.Timers.Timer
namespace. Additionally, I changed my code to use await and async, to make sure that the thread running the user interface is not frozen during the update. The new code is below:
// Timer for the CPU percentage check routine
public void InitTimer()
{
cpu_timer.Tick = new EventHandler(cpu_timer_Tick);
cpu_timer.Interval = 2000; // in miliseconds
cpu_timer.Start();
}
// Initates the checking routine
private async void cpu_timer_Tick(object sender, EventArgs e)
{
Task<string> cpu_task = new Task<string>(getCurrentCpuUsage);
cpu_task.Start();
cpu_usage.Text = await cpu_task;
}
CodePudding user response:
Like others are saying, I believe you want to execute the setting of the text on the UI thread... can try something like this:
// Initates the checking routine
private void cpu_timer_Tick(object sender, EventArgs e)
{
cpu_usage.Invoke((MethodInvoker)delegate {
// Running on the UI thread
cpu_usage.Text = getCurrentCpuUsage();
});
}