Re-using HttpClient but with a different Timeout setting per request?

后端 未结 2 702
悲&欢浪女
悲&欢浪女 2021-01-03 17:54

In order to reuse open TCP connections with HttpClient you have to share a single instance for all requests.

This means that we cannot simply i

相关标签:
2条回答
  • 2021-01-03 18:23

    Under the hood, HttpClient just uses a cancellation token to implement the timeout behavior. You can do the same directly if you want to vary it per request:

    var cts = new CancellationTokenSource();
    cts.CancelAfter(TimeSpan.FromSeconds(30));
    await httpClient.GetAsync("http://www.google.com", cts.Token);
    

    Note that the default timeout for HttpClient is 100 seconds, and the request will still be canceled at that point even if you've set a higher value at the request level. To fix this, set a "max" timeout on the HttpClient, which can be infinite:

    httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;
    
    0 讨论(0)
  • 2021-01-03 18:24

    The accepted answer is great, but I wanted to give another scenario for anyone looking for this in the future. In my case, I was already using a CancellationTokenSource that would cancel its token when the user chose to cancel. So in that case you can still use this technique by using the CreateLinkedTokenSource method of CancellationTokenSource. So in my scenario the http operation will cancel either by the timeout or the user's intervention. Here's a sample:

    public async static Task<HttpResponseMessage> SendRequest(CancellationToken cancellationToken)
    {
        var ctsForTimeout = new CancellationTokenSource();
        ctsForTimeout.CancelAfter(TimeSpan.FromSeconds(5));
        var cancellationTokenForTimeout = ctsForTimeout.Token;
    
        using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, cancellationTokenForTimeout))
        {
            try
            {
                return await httpClient.GetAsync("http://asdfadsf", linkedCts.Token);
            }
            catch
            {
                //just for illustration purposes
                if (cancellationTokenForTimeout.IsCancellationRequested)
                {
                    Console.WriteLine("timeout");
                }
                else if (cancellationToken.IsCancellationRequested)
                {
                    Console.WriteLine("other cancellation token cancelled");
                }
                throw;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题