WPF 任务管理器:处理刷新 CPU 加载值?
WPF Task Manager: Handling Refreshing CPU Load Value?
我目前对 c#/wpf(以及一般的编码)有些陌生。我决定开始另一个项目,作为定制的 "task manager" 之类的。
(虽然我使用了绑定,但这不是一个 MVVM 项目,所以欢迎大家回答)
如果您曾经打开过任务管理器,您就会知道它提供的主要有用工具之一是 CPU/RAM/Whatever 使用情况的更新视图。告诉用户他们正在使用的资源百分比。
我的问题是没有获得 CPU 百分比。我不确定如何在 UI 中有效地为 CPU 加载刷新文本 属性。
我的第一个想法是我应该创建一个后台工作程序(这可能是正确的)来分离线程负载。但是,我似乎无法全神贯注于以有用的方式实施后台工作人员的解决方案。
代码当前以这种方式设置:
- 加载页面时,public BgWrk 会自行创建一个新实例。
- 添加 运行 时调用的任务。
- BgWrk 是 运行。
- 创建要调用的方法的新实例。
- 在主线程上调用 Dispatcher 来更新 UI。
- 调用包括在 "grabber" 的 CpuPerUsed 的 return 值上设置 public 字符串 PerCpu(在其他 class 中绑定,使用 INotifyPropertyChanged & all)。 =39=]
- BgWrk 已处理。
程序循环(这很可能是问题所在)。
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
BgWrk = new BackgroundWorker();
BgWrk.DoWork += new DoWorkEventHandler(BackgroundWorker1_DoWork);
BgWrk.RunWorkerAsync();
}
private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
CpuInfoGrabber grabber = new CpuInfoGrabber();
Application.Current.Dispatcher.Invoke(new Action (() => Bnd.PerCpu = grabber.CpuPerUsed()));
BgWrk.Dispose();
}
}
代码再次工作,但由于检索所有数据的负载,它的速度很慢。任何有关如何使这项工作顺利进行的建议都将受到赞赏!
谢谢
您可以使用计时器定期轮询 CPU 使用情况,而不是循环。
class Test
{
private System.Timers.Timer _timer;
public Test( )
{
_timer = new System.Timers.Timer
{
// Interval set to 1 millisecond.
Interval = 1,
AutoReset = true,
};
_timer.Elapsed += _timer_Elapsed;
_timer.Enabled = true;
_timer.Start( );
}
private void _timer_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
{
// This handler is not executed on the gui thread so
// you'll have to marshal the call to the gui thread
// and then update your property.
var grabber = new CpuInfoGrabber();
var data = grabber.CpuPerUsed();
Application.Current.Dispatcher.Invoke( ( ) => Bnd.PerCpu = data );
}
}
在你的情况下我会使用 Task.Run
而不是 BackgroundWorker
:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
//Keep it running for 5 minutes
CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(hours: 0, minutes: 5, seconds: 0));
//Keep it running until user closes the app
//CancellationTokenSource cts = new CancellationTokenSource();
//Go to a different thread
Task.Run(() =>
{
//Some dummy variable
long millisecondsSlept = 0;
//Make sure cancellation not requested
while (!cts.Token.IsCancellationRequested)
{
//Some heavy operation here
Thread.Sleep(500);
millisecondsSlept += 500;
//Update UI with the results of the heavy operation
Application.Current.Dispatcher.Invoke(() => txtCpu.Text = millisecondsSlept.ToString());
}
}, cts.Token);
}
我目前对 c#/wpf(以及一般的编码)有些陌生。我决定开始另一个项目,作为定制的 "task manager" 之类的。
(虽然我使用了绑定,但这不是一个 MVVM 项目,所以欢迎大家回答)
如果您曾经打开过任务管理器,您就会知道它提供的主要有用工具之一是 CPU/RAM/Whatever 使用情况的更新视图。告诉用户他们正在使用的资源百分比。
我的问题是没有获得 CPU 百分比。我不确定如何在 UI 中有效地为 CPU 加载刷新文本 属性。
我的第一个想法是我应该创建一个后台工作程序(这可能是正确的)来分离线程负载。但是,我似乎无法全神贯注于以有用的方式实施后台工作人员的解决方案。
代码当前以这种方式设置:
- 加载页面时,public BgWrk 会自行创建一个新实例。
- 添加 运行 时调用的任务。
- BgWrk 是 运行。
- 创建要调用的方法的新实例。
- 在主线程上调用 Dispatcher 来更新 UI。
- 调用包括在 "grabber" 的 CpuPerUsed 的 return 值上设置 public 字符串 PerCpu(在其他 class 中绑定,使用 INotifyPropertyChanged & all)。 =39=]
- BgWrk 已处理。
程序循环(这很可能是问题所在)。
private void Grid_Loaded(object sender, RoutedEventArgs e) { BgWrk = new BackgroundWorker(); BgWrk.DoWork += new DoWorkEventHandler(BackgroundWorker1_DoWork); BgWrk.RunWorkerAsync(); } private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { while (true) { CpuInfoGrabber grabber = new CpuInfoGrabber(); Application.Current.Dispatcher.Invoke(new Action (() => Bnd.PerCpu = grabber.CpuPerUsed())); BgWrk.Dispose(); } }
代码再次工作,但由于检索所有数据的负载,它的速度很慢。任何有关如何使这项工作顺利进行的建议都将受到赞赏!
谢谢
您可以使用计时器定期轮询 CPU 使用情况,而不是循环。
class Test
{
private System.Timers.Timer _timer;
public Test( )
{
_timer = new System.Timers.Timer
{
// Interval set to 1 millisecond.
Interval = 1,
AutoReset = true,
};
_timer.Elapsed += _timer_Elapsed;
_timer.Enabled = true;
_timer.Start( );
}
private void _timer_Elapsed( object sender, System.Timers.ElapsedEventArgs e )
{
// This handler is not executed on the gui thread so
// you'll have to marshal the call to the gui thread
// and then update your property.
var grabber = new CpuInfoGrabber();
var data = grabber.CpuPerUsed();
Application.Current.Dispatcher.Invoke( ( ) => Bnd.PerCpu = data );
}
}
在你的情况下我会使用 Task.Run
而不是 BackgroundWorker
:
private void Grid_Loaded(object sender, RoutedEventArgs e)
{
//Keep it running for 5 minutes
CancellationTokenSource cts = new CancellationTokenSource(new TimeSpan(hours: 0, minutes: 5, seconds: 0));
//Keep it running until user closes the app
//CancellationTokenSource cts = new CancellationTokenSource();
//Go to a different thread
Task.Run(() =>
{
//Some dummy variable
long millisecondsSlept = 0;
//Make sure cancellation not requested
while (!cts.Token.IsCancellationRequested)
{
//Some heavy operation here
Thread.Sleep(500);
millisecondsSlept += 500;
//Update UI with the results of the heavy operation
Application.Current.Dispatcher.Invoke(() => txtCpu.Text = millisecondsSlept.ToString());
}
}, cts.Token);
}