【问题标题】:GUI freezes when using async/await使用 async/await 时 GUI 冻结
【发布时间】:2016-02-13 19:19:55
【问题描述】:

我试图找出下面的代码有什么问题。我认为使用 async 和 await 可以让我忘记诸如冻结之类的 GUI 问题,因为一些长代码阻塞了主线程。

单击按钮后,GUI 一直响应,直到调用longRunningMethod,如下所示:

 private async void openButton_Click(object sender, RoutedEventArgs e)
 {
    //doing some usual stuff before calling downloadFiles
    Task<int> result = await longRunningMethod(); // async method

    //at this point GUI becomes unresponsive

    //I'm using the result here, so I can't proceed until the longRunningMethod finishes

  }

在方法完成之前我无法继续,因为我需要result。为什么这段代码会冻结我的应用?

【问题讨论】:

  • longRunningMethod() 的内部可能因为没有正确使用async/await 而阻塞了 UI 线程
  • @Adwaenyth 这根本不是真的。 IO 绑定操作不需要新线程来停止阻塞 UI。
  • 我注意到您没有返回 Task。 longRunningMethod 是否启动新任务?
  • @DanielKelley 猜测它不是在方法中运行的 IO 绑定操作。
  • @user4205580 你能详细介绍一下longRunningMethod()里面的内容吗?

标签: c# wpf async-await


【解决方案1】:

问题出在longRunningMethod内。

代码可能做的是一些 CPU 绑定或阻塞操作。

如果你想在后台线程上运行一些 CPU 密集型代码,你必须明确地这样做; async 不会自动跳转线程:

int result = await Task.Run(() => longRunningMethod());

请注意,如果longRunningMethod 受 CPU 限制,则它应该具有同步 - 而非异步 - 签名。

如果longRunningMethod 不是 CPU-bound(即,它当前处于阻塞状态),那么您需要将longRunningMethod 中的阻塞方法调用更改为异步,并通过@987654328 调用它们@。然后你可以使longRunningMethod异步并通过await调用它:

int result = await longRunningMethodAsync();

【讨论】:

  • 我不确定我是否明白 - 当你按下一个按钮时,GUI 有一个异步方法被调用。当我调用await longRunningMethod 时,这意味着在longRunningMethod 完成之前不会执行按钮方法中的任何代码。到那时,执行会回到调用openButton_Click 方法的方法。执行异步方法longRunningMethod 应该创建一个单独的线程,对吧?正如我所说,这就是异步和等待的想法。
  • 什么是 CPU 绑定和阻塞操作?我认为第一个是当一个操作使用 100% 的 CPU 功率时,第二个是在等待一些资源时。但我认为这不会导致任何问题,例如 GUI 冻结(我认为在这种情况下多个线程也可以同时运行)
  • @user4205580:不,执行异步方法不会创建单独的线程。我有一个async/await intro post,您可能会觉得有帮助。
  • 忽略细节,我会说 async/await 是对多线程的模仿。两个不同的代码行在一个线程上轮流执行。如果其中一行需要很长时间才能运行,则在完成之前不会执行其他行。我说的对吗?
  • @user4205580:有点像。这对于 UI 线程上使用的异步是正确的,但对于任何其他场景(ASP.NET、线程池上的异步、控制台应用程序等)都不正确。
猜你喜欢
  • 2016-06-13
  • 2015-09-30
  • 1970-01-01
  • 2014-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多