Диспетчер задач WPF: обработка Обновление значения загрузки ЦП?

1
задан Aaron 13 July 2018 в 17:23
поделиться

2 ответа

Вместо циклирования вы можете использовать таймер для периодического опроса для использования ЦП.

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 );
    }
}
2
ответ дан WBuck 17 August 2018 в 12:20
поделиться
  • 1
    Я использовал оба этих ответа, чтобы исправить проблему. Должно было уделять больше внимания при отладке. Проблема заключалась в том, что, несмотря на то, что я использовал фоновых работников, я сделал тупую ошибку, поставив вызов метода в текущем диспетчере, заставляя пользовательский интерфейс работать ОЧЕНЬ медленно. – Aaron 13 July 2018 в 18:56
  • 2
    Я бы рекомендовал использовать DispatchTimer вместо ThreadingTimer в WPF, когда это возможно. Это означает, что вам не нужно иметь дело с перекрестными вызовами через Dispatcher, вы просто обновляете свойства напрямую. – Bradley Uffner 13 July 2018 в 19:09
  • 3
    Мне нужно будет опубликовать мой код, но я лично не использовал Dispatch Timer. Единственный Диспетчер, который я использовал, был сам Диспетчер (Current.Dispatcher ......). Честно говоря, вам не нужен таймер, если у вас есть правильная логика для потоков. Многопоточность распространяет процесс достаточно, где я могу обновить текущее использование примерно в 3-4 раза в среднем (работая на ЧРЕЗВЫЧАЙНО медленном компьютере, чтобы он знал, как долго). Поэтому, пока вы не используете свои вызовы методов в потоке пользовательского интерфейса, вы, вероятно, будете в порядке. – Aaron 13 July 2018 в 19:35
  • 4
    Хорошая вещь с подходом к таймеру - вы можете легко управлять разрешением без использования таких вещей, как Thread.Sleep, если вы работаете в цикле на фоновом потоке. На самом деле вам, вероятно, не нужно часто анализировать процессор (возможно, полсекунды до секунды). – WBuck 14 July 2018 в 13:24

Я использовал бы 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);
}
1
ответ дан Aly El-Haddad 17 August 2018 в 12:20
поделиться
  • 1
    Вероятно, в этом случае было бы целесообразно отметить метод делегата Task.Run как async, а затем использовать await Task.Delay( 500 ) вместо Thread.Sleep, чтобы вы не теряли совершенно хороший поток, заставляя его ждать. Если, конечно, вы не использовали это для дросселирования, а для имитации работы. – WBuck 13 July 2018 в 18:15
  • 2
    Я это понимаю - я просто симулирую тяжелую операцию. – Aly El-Haddad 13 July 2018 в 18:24
Другие вопросы по тегам:

Похожие вопросы: