繁体   English   中英

如何在不挂 gui 的情况下在 WPF 上运行异步任务

[英]How run async Task on WPF without hanging gui

我有用于监控数据的 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方法?

您可以使用异步循环。 尽管这看起来像一个无限循环,但实际上不是。 由于延迟任务的等待,此方法定期将控制权交还给其调用者。 如果这不是具有有效异步操作的异步方法,那么它将是一个同步方法,并且在我们调用它时会死锁 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);
        }
    });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM