有时候C#中的HttpClient请求失败

3

我在我的C# Windows应用程序中有类似的代码。

public async Task<HttpResponseMessage> SendHttpRequest()
{
    HttpResponseMessage response = null;
    try
    {
        HttpClient client = new HttpClient();
        string accessToken = await GetBearerToken(resourceUrl, clientId, clientSecret, tokenProviderUrl);
        if (!string.IsNullOrEmpty(accessToken))
            httpRequest.Headers.Add("Authorization", ("Bearer " + accessToken));

        response = await client.SendAsync(httpRequest);
    }
    catch(Exception ex)
    {
        log.Error("Exception raised while sending HTTP request");
        log.Error("Exception details : " + ex.Message);
    }           

    return response;
}

public async Task<string> GetBearerToken()
{           
    HttpResponseMessage response = null;
    HttpClient client = new HttpClient();
    string token = "";
    try
    {
        var request = new HttpRequestMessage(HttpMethod.Post, tokenProviderUrl);
        request.Content = new FormUrlEncodedContent(new Dictionary<string, string> {
            { "client_id",clientId},
            { "client_secret", clientSecret },
            { "grant_type", "client_credentials" },
            { "resource", resource },
        });

        response = await client.SendAsync(request);                
        var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
        token = payload.Value<string>("access_token");                
    }
    catch (HttpRequestException ex)
    {
        log.Error("Error in GetToken : " + ex.Message.ToString());
    }
    return token;
}

以上的代码大多数情况下都能正常工作。但偶尔会抛出异常,说“任务被取消”。根据一些问题和文章,我发现导致这种情况的原因可能有两个。
  1. 请求超时。
  2. 或者实际上请求被取消了。
我已经检查了此变量:CancellationToken.IsCancellationRequested。它返回false。所以我认为这是一个超时问题。为了基于这个超时,我还检查了请求开始和异常抛出之间的时间差。它恰好是100秒(这是httpClient的默认时间)。
现在,当我在5-10秒后立即重试相同的请求时,它会返回成功。由于这个问题并不是每个请求都会发生,我有点困惑到底发生了什么。
同样的请求95%的时间执行成功,剩下的5%时间则显示任务被取消。
是否存在同一个任务执行一次,取消一次的情况?
我通过Postman向Web API发送请求,从来没有遇到过这个问题。只有通过Windows应用程序才会遇到这个问题。
我是否遗漏了什么?

编辑

内部异常为空。
堆栈跟踪:在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)处 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)处处理非成功和调试器通知的任务 在System.Net.Http.HttpClient.d__58.MoveNext() ---异常抛出的前一个位置的堆栈跟踪结束--- 在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)处 在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)处处理非成功和调试器通知的任务 在System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()处。

这似乎与我上周遇到的问题类似。您可能需要调查客户端在请求期间是否已断开连接。 - RazorShorts
@RazorShorts 我该如何检查? - CrazyCoder
在SendHttpRequest()函数期间,检查完整的异常堆栈(或记录它)。而不仅仅是记录异常消息。甚至可能有一个内部异常,其中包含更多关于出错原因的详细信息。 - RazorShorts
@RazorShorts,我已经更新了我的答案,包括堆栈跟踪。 - CrazyCoder
@mtkachenko 是的。 - CrazyCoder
显示剩余2条评论
1个回答

0

每次想要发送请求时,你不应该创建一个新的 HttpClient。 在你的主方法中创建一个新的 HttpClient,然后在你的 "SendHttpRequest" 中传递它。 我之前遇到了类似的问题,任务取消时我进行了一些搜索并使用了这个方法。 对我来说有效。

HttpClient client = new HttpClient();
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Add("Connection", "Keep-Alive");
        client.DefaultRequestHeaders.Add("Keep-Alive", "false");
        client.Timeout = TimeSpan.FromMinutes(20);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接