Reputation: 53
Im currently messing around with a timer and a label and a performance counter because I am trying to make a label update its content to what ever the CPU usage is at the moment (and keeps updating at a certain interval)
But for some reason it just shows that my CPU usage is at 0% and its not updating.
What is causing this bug.
public void timerControl()
{
DispatcherTimer dtClockTime = new DispatcherTimer();
dtClockTime.Interval = new TimeSpan(0, 0, 1); //in Hour, Minutes, Second.
dtClockTime.Tick += dtClockTime_Tick;
dtClockTime.IsEnabled = true;
dtClockTime.Start();
}
private void dtClockTime_Tick(object sender, EventArgs e)
{
getCPUInfo();
}
public void getCPUInfo()
{
PerformanceCounter cpuCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
// Get Current Cpu Usage
string currentCpuUsage =
cpuCounter.NextValue() + "%";
//Print it to the current label
CPUUsage.Content = currentCpuUsage;
}
XAML
<Page x:Class="Hawk_PC.systemPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Hawk_PC"
mc:Ignorable="d"
Background="#03a3d2"
d:DesignHeight="350" d:DesignWidth="525"
Title="systemPage">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Label x:Name="osInfoLabel" Content="osInfoFriendlyName" HorizontalAlignment="Left" Margin="-206,-76,0,0" VerticalAlignment="Top"/>
<Image x:Name="image" HorizontalAlignment="Left" Height="83" Margin="-258,94,0,-119" VerticalAlignment="Top" Width="100" Source="Images/Logo.png"/>
<Label x:Name="osInfo" Content="OS:" HorizontalAlignment="Left" Margin="-234,-76,0,0" VerticalAlignment="Top"/>
<Label x:Name="ramInfo" Content="RAM:" HorizontalAlignment="Left" Margin="-234,-50,0,0" VerticalAlignment="Top"/>
<Label x:Name="hddInfo" Content="HDD Storage:" HorizontalAlignment="Left" Margin="-234,2,0,0" VerticalAlignment="Top"/>
<Label x:Name="systemHealth" Content="System Diagnose:" HorizontalAlignment="Left" Margin="-234,28,0,0" VerticalAlignment="Top"/>
<Label x:Name="cpuInfo" Content="CPU:" HorizontalAlignment="Left" Margin="-234,-24,0,0" VerticalAlignment="Top"/>
<Label x:Name="CPUUsage" Content="Label" HorizontalAlignment="Left" Margin="-190,-24,0,0" VerticalAlignment="Top"/>
<Button x:Name="startScanButton" Click="startScanButton_Click" Background="Transparent" BorderThickness="0" Content="Start Diagnose" HorizontalAlignment="Left" Margin="-258,55,0,-10" VerticalAlignment="Top" Width="137" Height="31"/>
</Grid>
</Page>
Upvotes: 1
Views: 119
Reputation: 2501
Replace the code in getCPUInfo() method with the below code,
/// <summary>
///
/// </summary>
public void getCPUInfo()
{
PerformanceCounter cpuCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
// Get Current Cpu Usage
cpuCounter.NextValue(); // Added
System.Threading.Thread.Sleep(1000); // Added
// now matches task manager reading
float secondValue = cpuCounter.NextValue(); // Added
string currentCpuUsage = secondValue + "%";
//Print it to the current label
CPUUsage.Content = currentCpuUsage;
}
And hope your problem will be resolved.
Upvotes: 1
Reputation: 10152
It appears that the method you're using might need a second call to NextValue()
and a pause between two calls to get it to work, based on https://blogs.msdn.microsoft.com/bclteam/2006/06/02/how-to-read-performance-counters-ryan-byington/ and comments in this SO post: How to get the CPU Usage in C#?
So, you'd modify your getCPUInfo()
method to look something like this:
public void getCPUInfo()
{
PerformanceCounter cpuCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
// Get Current Cpu Usage
cpuCounter.NextValue();
// Sleep
Thread.Sleep(1000);
// Get Current Cpu Usage again
string currentCpuUsage = cpuCounter.NextValue() + "%";
//Print it to the current label
CPUUsage.Content = currentCpuUsage;
}
Obviously, I hope that you understand that using Thread.Sleep()
in a UI-centric program is a bad thing, so I'd use tasks and delays if you were to go with this approach (I just don't know how familiar you are with TPL, so I didn't want to bring in any further confusion).
Here's the demo of it working:
With that being said, you can solve everything by simply doing something like this:
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Threading;
namespace TestApp
{
public partial class MainWindow : Window
{
PerformanceCounter cpuCounter;
DispatcherTimer dtClockTime;
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
InitializeCpuPerformanceCounter();
InitializeDispatcherTimer();
}
void InitializeDispatcherTimer()
{
dtClockTime = new DispatcherTimer();
dtClockTime.Interval = new TimeSpan(0, 0, 1); //in Hour, Minutes, Second.
dtClockTime.Tick += dtClockTime_Tick;
dtClockTime.IsEnabled = true;
dtClockTime.Start();
}
void InitializeCpuPerformanceCounter()
{
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
}
private void dtClockTime_Tick(object sender, EventArgs e)
{
getCPUInfo();
}
public void getCPUInfo()
{
CPUUsage.Content = cpuCounter.NextValue() + "%";
}
}
}
Here's a demo:
It's working due to the fact that I am not instantiating a new performance counter on every tick and since the timer has a one second interval, that causes the needed delay between each NextValue()
call. I store both the PerformanceCounter
and the DispatcherTimer
as fields and initialize only once. So, this is a much better approach.
By the way, the XAML code for both tests is incredibly simple:
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestApp"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="525">
<Grid>
<Label x:Name="CPUUsage" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Window>
EDIT:
Per your request in the comments, here's something that would make use of async
and await
if you were to stay with the original approach. This will prevent the UI from freezing up for one second every other second, as it would do with the Thread.Sleep()
version:
public async Task getCPUInfo()
{
PerformanceCounter cpuCounter;
cpuCounter = new PerformanceCounter();
cpuCounter.CategoryName = "Processor";
cpuCounter.CounterName = "% Processor Time";
cpuCounter.InstanceName = "_Total";
// Get Current Cpu Usage
cpuCounter.NextValue();
// Delay
await Task.Delay(1000);
// Get Current Cpu Usage again
string currentCpuUsage = cpuCounter.NextValue() + "%";
//Print it to the current label
CPUUsage.Content = currentCpuUsage;
}
You may find more information on TPL on MSDN:
https://msdn.microsoft.com/en-us/library/dd460717(v=vs.110).aspx
Additionally, I can't recommend Stephen Cleary's blog enough. It's a gem. Here's an article on async
and await
:
http://blog.stephencleary.com/2012/02/async-and-await.html
He has a lot of other articles as well and his book is top notch (although, if you can't afford it, all the content in that book is throughout his blog -- he's a good guy).
Upvotes: 2