我有一个试图使用某些async
代码的WebForms项目。在早期开发期间,我只是在async
中调用Page_Load
代码(也是async
)并将结果写入Response
。很好,很容易测试。这一切都按预期工作。
代码可以概括为:
因此,当我尝试在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
中调用此代码时遇到此问题?我该怎么做才能解决问题?
答案 0 :(得分:0)
改变你的
IRestResponse<JObject> response = await client.Execute<JObject>(request);
到
IRestResponse<JObject> response = await client.Execute<JObject>(request).ConfigureAwait(false);
这对你有帮助吗? 问题是两个“await”都在等待同时捕获相同的上下文,ConfigureWait阻止这个(读取它的doc)