C# 使用异步/等待时GUI冻结

C# 使用异步/等待时GUI冻结,c#,wpf,async-await,C#,Wpf,Async Await,我正试图找出下面的代码出了什么问题。我认为使用async和await可以让我忘记GUI问题,比如冻结,因为一些长代码阻塞了主线程 单击按钮后,GUI会一直响应,直到调用longRunningMethod,如下所示: private async void openButton_Click(object sender, RoutedEventArgs e) { //doing some usual stuff before calling downloadFiles Task&l

我正试图找出下面的代码出了什么问题。我认为使用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

  }
private async void openButton\u单击(对象发送器,路由目标)
{
//在调用downloadFiles之前做一些常规工作
任务结果=等待longRunningMethod();//异步方法
//此时GUI变得无响应
//我在这里使用的是结果,所以在longRunningMethod完成之前我无法继续
}

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

问题出在
longRunningMethod

代码可能正在执行一些CPU限制或阻塞操作

如果你想在后台线程上运行一些CPU绑定的代码,你必须显式地这样做<代码>异步不会自动跳转线程:

int result = await Task.Run(() => longRunningMethod());
请注意,如果
longRunningMethod
受CPU限制,则它应该具有同步签名,而不是异步签名

如果
longRunningMethod
不受CPU限制(即当前正在阻塞),则需要将
longRunningMethod
中的阻塞方法调用更改为异步,并通过
wait
调用它们。然后您可以使
longRunningMethod
异步,并通过
wait
调用它:

int result = await longRunningMethodAsync();

longRunningMethod()
的内部可能由于未使用
async/await
properly@Adwaenyth那根本不是真的。IO绑定操作不需要新线程来停止阻止UI。我注意到您没有返回任务。longRunningMethod是否启动新任务?@DanielKelley猜测该方法中运行的不是IO绑定操作。@user4205580您能否提供一些有关
longRunningMethod()
内部内容的详细信息?我不确定是否得到了它-当您按下按钮时,GUI会调用一个异步方法。当我调用
await longRunningMethod
时,这意味着在
longRunningMethod
完成之前,不会执行button方法中的任何代码。此时,执行返回到名为
openButton\u Click
method的方法。执行异步方法
longRunningMethod
应该创建一个单独的线程,对吗?正如我所说的,这就是异步和等待的思想。什么是CPU绑定和阻塞操作?我认为第一个是当一个操作使用100%的CPU功率时,第二个是当一些资源被等待时。但是我不认为这会导致任何问题,比如GUI冻结(我认为在这种情况下多个线程也可以同时运行)@user4205580:不,执行异步方法不会创建单独的线程。我有一个你可能会觉得有用的例子。忽略细节,我认为async/await是对多线程的模仿。两段不同代码的行在单个线程上轮流执行。如果其中一行需要很长时间才能运行,则在完成之前不会执行其他行。我说得对吗?@user4205580:有点。这对于UI线程上使用的异步是正确的,但对于任何其他场景(ASP.NET、线程池上的异步、控制台应用程序等)都不正确。