简体   繁体   English

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

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

I Have WPF App for Monitoring data and I write Task.Run in Loaded method to do work and show data in GUI.我有用于监控数据的 WPF 应用程序,我在 Loaded 方法中编写Task.Run来完成工作并在 GUI 中显示数据。

The code looks like below:代码如下所示:

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

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

void DoAddAsync()
{

  while (true)

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

It works fine and I can change component in GUI without hanging.它工作正常,我可以在不挂起的情况下更改 GUI 中的组件。

But if I execute a method in this.Dispatcher.Invoke , GUI is hanging and I can't do anything until that method closed.但是,如果我在this.Dispatcher.Invoke执行一个方法,GUI 就会挂起,在该方法关闭之前我什么也做不了。

Anybody can help me to run method in this.Dispatcher.Invoke without hanging GUI?任何人都可以帮助我在不挂 GUI 的情况下运行this.Dispatcher.Invoke方法?

You can use an asynchronous loop.您可以使用异步循环。 Even though this looks like an infinite loop, its really not.尽管这看起来像一个无限循环,但实际上不是。 Because of the await of the delay Task, this method yields control back to the its caller periodically.由于延迟任务的等待,此方法定期将控制权交还给其调用者。 If this weren't an async method with a valid asynchronous operation, it would be a synchronous method and would deadlock the UI when we called it.如果这不是具有有效异步操作的异步方法,那么它将是一个同步方法,并且在我们调用它时会死锁 UI。

But since it is not, it works as needed and gives you both a very clear intent of what the code is supposed to do as well as keeps us on the UI thread the whole time (the magic of await!) so we don't have multithreaded issues or multiple delegates/callbacks.但由于它不是,它可以根据需要工作,并为您提供代码应该做什么的非常清晰的意图,并让我们始终保持在 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);
    }
}

The real trick to making this work though, is not in the DoAddAsync method.但是,使这项工作发挥作用的真正技巧不在 DoAddAsync 方法中。 Its how we call it.它是我们如何称呼它的。 You do not await the call to it.您无需等待对它的调用。

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

You can also update your way but it introduces multiple delegates, potential multithreading complexities depending on the work being done and we still have to get back onto the UI thread to update the UI.你也可以更新你的方式,但它会引入多个委托,潜在的多线程复杂性取决于正在完成的工作,我们仍然必须回到 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