WebMethod中的异步函数死锁,但在Page_Load

时间:2015-12-08 00:28:36

标签: c# asynchronous webforms webmethod

我有一个试图使用某些async代码的WebForms项目。在早期开发期间,我只是在async中调用Page_Load代码(也是async)并将结果写入Response。很好,很容易测试。这一切都按预期工作。

代码可以概括为:

  1. 获取Azure授权令牌。
  2. 向Azure的REST API发出HTTP请求。
  3. 将结果返回给客户。
  4. 因此,当我尝试在async内调用此WebMethod方法时,我感到非常惊讶,但它失败了。它似乎在其他async代码(特别是Azure AD AuthenticationContext.AcquireTokenAsync方法)上陷入僵局。

    我的第一个想法是某些背景巫术,但ConfigureAwait(false)没有任何效果。所以我对于不同的东西感到很茫然。我已尝试使用WebMethod async,但结果没有差异。快速测试表明,WebMethod的配置方式没有任何问题 - 让我的代码早期返回(在调用AD代码之前)让它按预期工作。虽然当时没有发生任何异步。

    我还尝试使用非异步方法获取Azure AD令牌。这很好,但是当我的应用程序尝试发出HTTP请求时(使用RestSharp.Portable库,它只提供async方法),它会被卡住。我的代码看起来像:

    protected async Task<JObject> PerformRequest(string path, Method method, string apiVersion, string requestBody)
    {
        RestClient client = new RestClient("https://management.azure.com");
        RestRequest request = new RestRequest(path, method);
        request.AddParameter("api-version", apiVersion);
        request.AddHeader("Authorization", await this.GetAccessTokenAsync());
        IRestResponse<JObject> response = await client.Execute<JObject>(request);
        return response.Data;
    }
    

    我的工作Page_Load和非工作WebMethod使用的代码几乎完全相同,只是WebMethod返回结果而Page_Load将结果写入{ {1}}。

    Response看起来像:

    GetAccessToken

    所有这一切的调用都是直接在public async Task<string> GetAccessTokenAsync() { string tenantId = "xxx"; AuthenticationContext authenticationContext = new AuthenticationContext($"https://login.windows.net/{tenantId}"); ClientCredential credential = new ClientCredential(clientId: "xxx", clientSecret: "xxx="); AuthenticationResult result = await authenticationContext.AcquireTokenAsync(resource: "https://management.core.windows.net/", clientCredential: credential); if (result == null) throw new InvalidOperationException("Failed to obtain the JWT token"); return this.accessToken = result.AccessTokenType + " " + result.AccessToken; } 中进行的(这是WebMethod目前唯一的做法):

    WebMethod

    为什么我的应用程序在return await this.PerformRequest("xxx", Method.GET, "xxx", null).ContinueWith(result => result.ToString()); 中调用此代码而在WebMethod中调用此代码时遇到此问题?我该怎么做才能解决问题?

1 个答案:

答案 0 :(得分:0)

改变你的

IRestResponse<JObject> response = await client.Execute<JObject>(request);

IRestResponse<JObject> response = await client.Execute<JObject>(request).ConfigureAwait(false);

这对你有帮助吗? 问题是两个“await”都在等待同时捕获相同的上下文,ConfigureWait阻止这个(读取它的doc)