获取异步结果死锁(尽管将 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 应用程序中阻止任何地方 - 只需禁用在等待令牌返回时不得使用的任何控件,并在它返回时启用它们。