我正在做一些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
但是在通过向GetRefreshTokenAsync()方法添加.ConfigureAwait(false)来尝试他的方法1后,它没有任何区别。
有什么建议吗?
答案 0 :(得分:5)
它使应用程序陷入僵局:(
这就是在具有自定义同步的环境中对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
}
答案 1 :(得分:1)
如果您访问任务的Result属性,它将充当Future并且它将阻止当前线程,直到Task返回结果。
我认为你实际上并没有陷入僵局,但你正在等待的任务永远不会完成。
确保您对OAuth.GetRefreshTokenAsync的调用返回。
答案 2 :(得分:1)
您需要确保RenewAuthentication
的结果不会被编组回UI线程。 ConfigureAwait(false)
几乎完全出于以下目的:
var renewAwaitable = RenewAuthentication().ConfigureAwait(false);
var result = renewAwaitable.GetAwaiter().GetResult();
但是,我建议改为使用async全力以赴。在UI应用程序中阻止任何地方都没有理由 - 只需禁用在等待令牌返回时不得使用的任何控件,并在启用时启用它们。
答案 3 :(得分:-1)
async
代码是一直构造。你不能做半异步,不应该试图强迫它。 noAsync
似乎没有任何用处。
在他的智慧中,Cleary先生清楚地表明每个async
方法都有自己的上下文,可以在UI上继续运行。
您能确定OAuth.GetRefreshTokenAsync
在内部使用ConfigureAwait(false)
吗?如果它没有,你将陷入僵局。