如何在WPF上运行异步任务而不挂gui

问题描述 投票:2回答:1

我有用于监控数据的WPF应用程序,我在Loaded方法中编写Task.Run来完成工作并在GUI中显示数据。

代码如下所示:

private async void Window_Loaded(object sender, RoutedEventArgs e)
{

        await Task.Run(() => DoAddAsync());
}

void DoAddAsync()
{

  while (true)

  {
       this.Dispatcher.Invoke(() =>
       {
              //Do Some
       });
  }
}

它工作正常,我可以在不挂起的情况下更改GUI中的组件。

但是如果我在this.Dispatcher.Invoke中执行一个方法,GUI就会挂起,在该方法关闭之前我无法做任何事情。

任何人都可以帮我在没有挂GUI的情况下在this.Dispatcher.Invoke中运行方法?

c# wpf task invoke dispatcher
1个回答
1
投票

您可以使用异步循环。虽然这看起来像一个无限循环,但实际上并非如此。由于等待延迟任务,此方法会定期将控制权返回给其调用者。如果这不是具有有效异步操作的异步方法,那么它将是一个同步方法,并且在我们调用它时会使UI死锁。

但是既然它不是,它可以根据需要工作,并且给你一个非常明确的意图,代码应该做什么,以及让我们一直在UI线程(等待的魔力!)所以我们不有多线程问题或多个代理/回调。

private async Task DoAddAsync()
{
    while (true)
    {
        // do the work in the loop
        // ....
        // don't run again for at least 200 milliseconds
        await Task.Delay(200);
    }
}

实现这个功能的真正技巧不在于DoAddAsync方法。我们如何称呼它。你不等待它的调用。

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
     DoAddAsync()
}

您也可以更新自己的方式,但它会引入多个委托,潜在的多线程复杂性取决于正在完成的工作,我们仍然需要回到UI线程来更新UI。

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    await Task.Run(async () =>
    {
        while (true)
        {
            // do the work in the loop

            // update the UI on the UI thread
            Dispatcher.Invoke(() => // do some );

            // don't run again for at least 200 milliseconds
            await Task.Delay(200);
        }
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.