我有一個試圖利用一些async
代碼的WebForms項目工作正常。在早期發育過程,我只是要求我在Page_Load
async
代碼(這也是async
),並將結果寫入Response
。很好,很容易進行測試。這一切都按預期工作。異步功能死鎖,但如果調用在Page_Load中
的代碼可以總結爲:
- 獲取Azure的授權令牌。
- 朝着Azure的REST API的HTTP請求。
- 將結果返回給客戶端。
我很驚訝,因此,當我試圖在WebMethod
內調用這個async
方法時,它失敗了。它似乎在其他async
代碼(特別是Azure AD AuthenticationContext.AcquireTokenAsync
方法)上發生了死鎖。
我首先想到的是一些背景巫術,但ConfigureAwait(false)
沒有任何效果。所以我對於什麼是不同的而感到茫然。我試過WebMethod
爲async
或者沒有結果差異。快速測試顯示,有什麼錯WebMethod
是如何配置的 - 有我的代碼返回初以來它的工作如預期(達到調用廣告代碼之前)。雖然沒有什麼異步的事情發生。
我也使用用於獲取天青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
寫結果到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
中沒有此問題?我能做些什麼來解決這個問題?
我們可以看到你調用'PerformRequest'的地方嗎?你在任何地方等待'PerformRequest'調用的結果嗎? – spender
你可以將代碼發佈到this.GetAccessToken嗎? – Aron
另外,請你可以發佈運行此代碼的結果與HTTP嗅探器,如提琴手。 – Aron