Reputation: 6394
I'm trying to run a look to update CPU Usage onto a progress bar from a thread.
The code I have here is:
private static int _cpuUsage;
protected PerformanceCounter cpuCounter;
private Thread thread;
public CPUUsageIndModel()
{
cpuCounter = new PerformanceCounter
{CategoryName = "Processor", CounterName = "% Processor Time", InstanceName = "_Total"};
thread = new Thread(GetCurrentCpuUsage);
thread.Start();
}
public void GetCurrentCpuUsage()
{
while (true)
{
_cpuUsage = Convert.ToInt32(Math.Round(cpuCounter.NextValue()));
Thread.Sleep(1000);
}
}
public int GetCPUUsage
{
get { return _cpuUsage; }
set
{
_cpuUsage = value;
NotifyPropertyChanged("_cpuUsage");
}
}
Now the thing is I've tried starting the thread with just:
public void GetCurrentCpuUsage()
{
_cpuUsage = 40;
}
And it works fine, so that leaves the cpuCounter
and loop used.
Can anyone point out any mistake that I may have made.
Thanks
EDIT - Complete Class and some minor tweaks:
public class CPUUsageIndModel : INotifyPropertyChanged
{
public static int _cpuUsage;
protected PerformanceCounter cpuCounter;
private Thread thread;
public CPUUsageIndModel()
{
cpuCounter = new PerformanceCounter
{CategoryName = "Processor", CounterName = "% Processor Time", InstanceName = "_Total"};
thread = new Thread(GetCurrentCpuUsage);
thread.Start();
}
public void GetCurrentCpuUsage()
{
while (true)
{
CPUUsage = Convert.ToInt32(Math.Round(cpuCounter.NextValue()));
Thread.Sleep(1000);
}
}
public int CPUUsage
{
get { return _cpuUsage; }
set
{
_cpuUsage = value;
NotifyPropertyChanged("_cpuUsage");
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
}
Upvotes: 0
Views: 1230
Reputation: 1140
Looks like you got it almost right, at least looking from the edit. Only, you are raising the property changed on a field name instead of the property name. Here is the fix:
public int CPUUsage
{
get { return _cpuUsage; }
set
{
_cpuUsage = value;
NotifyPropertyChanged("CPUUsage"); // Notify CPUUsage not _cpuUsage
}
}
and your binding should look like {Binding Path=CPUUsage}
Upvotes: 1
Reputation: 6911
You need to notify WPF runtime of the change. For that purpose you implement INotifyPropertyChanged
interface.
You seem to attempt that here, but you're not doing it the right way (you didn't display all of relevant code but I fairly sure your implementation is not correct).
You need to: 1. Bind to a public property (we don't see this in code you pasted) 2. Send notification from setter of the property, if value is changed 3. Change the value through property setter
You may be doing point one correctly, we don't see this, but you are notifying that private field changed, and you should notify that property changed (NotifyPropertyChanged("GetCPUUsage")
). You are also setting the value by directly accessing field (_cpuUsage = 40;
), and you should do it through setter (GetCPUUsage = 40;
).
In this context your property name is a bit strange. I'd rename GetCPUUsage
to CPUUsage
, as you can get and set it's value. Also prefix Get should be used for methods, not properties.
Upvotes: 1