簡體   English   中英

WebMethod中的異步函數死鎖,但如果在Page_Load中調用,則可以正常工作

[英]Async function deadlocks in WebMethod, but works fine if called in Page_Load

我有一個WebForms項目,試圖利用一些async代碼。 在早期開發期間,我只是在Page_Load (也是async )中調用async代碼,然后將結果寫入Response 易於測試。 一切都按預期進行。

該代碼可以總結為:

  1. 獲取Azure授權令牌。
  2. 向Azure的REST API發出HTTP請求。
  3. 將結果返回給客戶。

因此,當我嘗試在WebMethod調用此async方法而失敗時,我感到非常驚訝。 它似乎在其他async代碼(特別是Azure AD AuthenticationContext.AcquireTokenAsync方法)上陷入僵局。

我的第一個想法是一些上下文魔術,但是ConfigureAwait(false)沒有任何作用。 因此,我對不同之處一無所知。 我嘗試過WebMethod是否async ,結果沒有差異。 快速測試表明,此WebMethod的配置沒有任何問題-讓我的代碼盡早返回(在到達AD代碼之前)可以按預期工作。 盡管那時沒有異步發生。

我還嘗試使用非異步方法來獲取Azure AD令牌。 這可以正常工作,但是當我的應用程序嘗試發出HTTP請求時(使用僅提供async方法的RestSharp.Portable庫),它被卡住了。 我的代碼在那里:

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將結果寫入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中而不是Page_Load調用此代碼時可能會遇到此問題? 我該如何解決該問題?

改變你的

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

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

這對您有幫助嗎? 問題是兩個“ await”都在等待同時捕獲同一上下文,ConfigureWait阻止了此操作(請閱讀其文檔)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM