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

boo*_*ife 24 .net dotnet-httpclient

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

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

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

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

Tod*_*ier 41

在引擎盖下,HttpClient只需使用取消令牌来实现超时行为.如果您想根据请求更改它,可以直接执行相同的操作:

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

请注意,默认超时为HttpClient100秒,即使您在请求级别设置了更高的值,该请求仍将在该点取消.要解决此问题,请在其上设置"max"超时,该超时HttpClient可以是无限的:

httpClient.Timeout = System.Threading.Timeout.InfiniteTimeSpan;
Run Code Online (Sandbox Code Playgroud)

  • 正如另一个答案中提到的那样,这只能减少取消时间。因此,如果计划使用此方法,则最好将默认超时设置为无限(或您可以满意的其他数量),并计划为每个**请求**提供自己的取消令牌。 。 (2认同)

Bra*_*ght 5

接受的答案很好,但我想为将来寻找这个的人提供另一种情况。就我而言,我已经在使用 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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)