获取异步结果死锁(尽管将 configure await 设置为 false)
Getting async result deadlocking (despite setting configure await to false)
我正在做一些 OAuth 工作,我通过提供的异步 API 方法 (GetRefreshTokenAsync) 获取刷新令牌:
public async Task<Tokens> RenewAuthentication()
{
AppTokenResult token = await OAuth.GetRefreshTokenAsync("clientid",
"clientsecret",
@"myRefreshToken");
string accessToken = token.AccessToken;
string refreshToken = token.RefreshToken;
return new Tokens(accessToken, refreshToken);
}
如果我像这样从非异步方法调用它:
public void noAsync()
{
var r = RenewAuthentication();
var x = r.Result;
}
它使应用程序死锁 :(。如果我删除第二行 (r.Result),那么它就可以工作,但那是废话,因为我无法得到结果。我尝试阅读
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
但是在通过将 .ConfigureAwait(false) 添加到 GetRefreshTokenAsync() 方法来尝试他的方法 1 之后,它没有任何区别。
有什么建议吗?
如果您访问任务的结果 属性,它将充当 Future 并且它将阻塞当前线程,直到任务 returns 获得结果。
我不认为你真的遇到了死锁,但你正在等待的任务永远不会完成。
确保您拨打 OAuth.GetRefreshTokenAsync returns。
async
代码是一个 一路 结构。你不能做半异步,不应该试图强制它。 noAsync
似乎在这里没有任何用处。
Cleary 先生以他的智慧明确指出,每个 async
方法都有自己的上下文,在该上下文中它可以 运行 在 UI 上继续。
您能确定 OAuth.GetRefreshTokenAsync
正在内部使用 ConfigureAwait(false)
吗?如果没有,您将陷入僵局。
It deadlocks the app :(
这就是在具有自定义同步的环境中阻塞 async
方法的效果。
如果您在 "FormLoad" 上调用此方法,则无需阻止。只需将您的事件处理程序标记为 async
,这样您就可以 await
操作:
public Form()
{
this.Load += OnLoadHandler;
}
public async void OnLoadHandler(object sender, EventArgs e)
{
var result = await RenewAuthenticationAsync();
// Store the result here
}
您需要确保 RenewAuthentication
的结果不会编组回 UI 线程。 ConfigureAwait(false)
几乎完全是为了这样的目的:
var renewAwaitable = RenewAuthentication().ConfigureAwait(false);
var result = renewAwaitable.GetAwaiter().GetResult();
但是,我建议全力以赴使用异步。没有理由在 UI 应用程序中阻止任何地方 - 只需禁用在等待令牌返回时不得使用的任何控件,并在它返回时启用它们。
我正在做一些 OAuth 工作,我通过提供的异步 API 方法 (GetRefreshTokenAsync) 获取刷新令牌:
public async Task<Tokens> RenewAuthentication()
{
AppTokenResult token = await OAuth.GetRefreshTokenAsync("clientid",
"clientsecret",
@"myRefreshToken");
string accessToken = token.AccessToken;
string refreshToken = token.RefreshToken;
return new Tokens(accessToken, refreshToken);
}
如果我像这样从非异步方法调用它:
public void noAsync()
{
var r = RenewAuthentication();
var x = r.Result;
}
它使应用程序死锁 :(。如果我删除第二行 (r.Result),那么它就可以工作,但那是废话,因为我无法得到结果。我尝试阅读
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
但是在通过将 .ConfigureAwait(false) 添加到 GetRefreshTokenAsync() 方法来尝试他的方法 1 之后,它没有任何区别。
有什么建议吗?
如果您访问任务的结果 属性,它将充当 Future 并且它将阻塞当前线程,直到任务 returns 获得结果。
我不认为你真的遇到了死锁,但你正在等待的任务永远不会完成。
确保您拨打 OAuth.GetRefreshTokenAsync returns。
async
代码是一个 一路 结构。你不能做半异步,不应该试图强制它。 noAsync
似乎在这里没有任何用处。
Cleary 先生以他的智慧明确指出,每个 async
方法都有自己的上下文,在该上下文中它可以 运行 在 UI 上继续。
您能确定 OAuth.GetRefreshTokenAsync
正在内部使用 ConfigureAwait(false)
吗?如果没有,您将陷入僵局。
It deadlocks the app :(
这就是在具有自定义同步的环境中阻塞 async
方法的效果。
如果您在 "FormLoad" 上调用此方法,则无需阻止。只需将您的事件处理程序标记为 async
,这样您就可以 await
操作:
public Form()
{
this.Load += OnLoadHandler;
}
public async void OnLoadHandler(object sender, EventArgs e)
{
var result = await RenewAuthenticationAsync();
// Store the result here
}
您需要确保 RenewAuthentication
的结果不会编组回 UI 线程。 ConfigureAwait(false)
几乎完全是为了这样的目的:
var renewAwaitable = RenewAuthentication().ConfigureAwait(false);
var result = renewAwaitable.GetAwaiter().GetResult();
但是,我建议全力以赴使用异步。没有理由在 UI 应用程序中阻止任何地方 - 只需禁用在等待令牌返回时不得使用的任何控件,并在它返回时启用它们。