【发布时间】:2019-05-31 12:30:39
【问题描述】:
我有这段代码来调用返回令牌的 API。但是,只有当我替换此行时它才会返回:
var response = await TokenClient.PostAsync(EnvironmentHelper.TokenUrl, formContent);
用这一行:
var response = TokenClient.PostAsync(EnvironmentHelper.TokenUrl, formContent).Result;
为什么?
public static async Task<Token> GetAPIToken()
{
if (DateTime.Now < Token.Expiry)
return Token;
TokenClient.DefaultRequestHeaders.Clear();
TokenClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
TokenClient.BaseAddress = new Uri(EnvironmentHelper.BaseUrl);
TokenClient.Timeout = TimeSpan.FromSeconds(3);
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", EnvironmentHelper.APITokenClientId),
new KeyValuePair<string, string>("client_secret", EnvironmentHelper.APITokenClientSecret)
});
try
{
// HANGS - this next line will only ever return if suffixed with '.Result'
var response = await TokenClient.PostAsync(EnvironmentHelper.TokenUrl, formContent);
var content = await response.Content.ReadAsStringAsync();
dynamic jsonContent = JsonConvert.DeserializeObject(content);
Token token = new Token();
token.AccessToken = jsonContent.access_token;
token.Type = jsonContent.token_type;
token.Expiry = DateTimeOffset.Now.AddSeconds(Convert.ToDouble(jsonContent.expires_in.ToString()) - 30);
token.Scope = Convert.ToString(jsonContent.scope).Split(' ');
Token = token;
}
catch (Exception ex)
{
var m = ex.Message;
}
return Token;
}
【问题讨论】:
-
你怎么打电话给
GetAPIToken?你是awaiting 一路向上吗? -
@DavidG - 差不多。不执行等待的最顶层代码如下: var wm = new WebRepo().GetWeb(Id).Result;
-
是的,不要那样做。一直使用
await,否则您将面临像您所看到的那样陷入僵局的危险。 -
@MattW 真正的解决方案是删除所有
.Result或.Wait()调用,使用async/await一直到顶部。另一种选择是使用ConfigureAwait(false),这意味着您的代码不会返回到 UI 线程。这意味着您也无法修改 UI -
根据函数的使用情况,您的程序肯定会陷入死锁。如果调用代码不是异步的,则将其包装在一个任务中并等待方法调用并删除 .Result
标签: c# async-await httpclient .net-4.6.1