重新使用HttpClient但每个请求有不同的超时设置?

时间:2017-10-22 13:36:04

标签: .net dotnet-httpclient

为了重用与HttpClient的开放式TCP连接,您必须为所有请求共享一个实例。

这意味着我们无法使用不同的设置(例如超时或标头)简单地实例化HttpClient

我们如何共享连接并同时使用不同的设置?这很简单,实际上是默认设置,使用较早的HttpWebRequestWebClient基础设施。

请注意,在发出请求之前简单地设置HttpClient.Timeout不是线程安全的,并且不能在并发应用程序(例如ASP.NET网站)中工作。

2 个答案:

答案 0 :(得分:32)

在幕后,HttpClient只使用取消令牌来实现超时行为。如果您想根据请求改变它,可以直接执行相同操作:

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

请注意,HttpClient的默认超时为100秒,即使您在请求级别设置了较高的值,该请求仍会在此时取消。要解决此问题,请在HttpClient上设置“最大”超时,这可能是无限的:

httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;

答案 1 :(得分:0)

可接受的答案很好,但是我想为将来寻求此解决方案的任何人提供另一个方案。就我而言,我已经在使用CancellationTokenSource,当用户选择取消时,它将取消其令牌。因此,在那种情况下,您仍然可以通过使用CancellationTokenSource的CreateLinkedTokenSource方法来使用此技术。因此,在我的情况下,http操作将因超时或用户的干预而取消。这是一个示例:

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;
        }
    }
}