WPF 任务管理器:处理刷新 CPU 加载值?

WPF Task Manager: Handling Refreshing CPU Load Value?

我目前对 c#/wpf(以及一般的编码)有些陌生。我决定开始另一个项目,作为定制的 "task manager" 之类的。

(虽然我使用了绑定,但这不是一个 MVVM 项目,所以欢迎大家回答)

如果您曾经打开过任务管理器,您就会知道它提供的主要有用工具之一是 CPU/RAM/Whatever 使用情况的更新视图。告诉用户他们正在使用的资源百分比。

我的问题是没有获得 CPU 百分比。我不确定如何在 UI 中有效地为 CPU 加载刷新文本 属性。

我的第一个想法是我应该创建一个后台工作程序(这可能是正确的)来分离线程负载。但是,我似乎无法全神贯注于以有用的方式实施后台工作人员的解决方案。

代码当前以这种方式设置:

  1. 加载页面时,public BgWrk 会自行创建一个新实例。
  2. 添加 运行 时调用的任务。
  3. BgWrk 是 运行。
  4. 创建要调用的方法的新实例。
  5. 在主线程上调用 Dispatcher 来更新 UI。
  6. 调用包括在 "grabber" 的 CpuPerUsed 的 return 值上设置 public 字符串 PerCpu(在其他 class 中绑定,使用 INotifyPropertyChanged & all)。 =39=]
  7. BgWrk 已处理。
  8. 程序循环(这很可能是问题所在)。

    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);
}