Search code examples
c#dotnet-httpclientcancellationtokensourcecancellation-token

HttpClient cancellation doesn't kill underlying TCP call


I'm trying to set a default timeout for my HttpClient calls to 5 seconds.

I've done this via CancellationTokenSource.

Here's the pertinent bit of code:

var cancellationToken = new CancellationTokenSource();
cancellationToken.CancelAfter(TimeSpan.FromSeconds(5));
var result = _httpClient.SendAsync(request, cancellationToken.Token);

Works as i expected in terms of the calling code getting a "Task was cancelled" error (i tested in a .NET 4.7 console app), but i noticed in Fiddler the request was still running for 1 minute, until it finally gave up:

enter image description here

Can someone explain this behaviour?

I would expect the underlying request to also get cancelled when the cancellation is triggered.

_httpClient is instantiated like: new HttpClient { BaseAddress = baseAddress }

I know there's the the Timeout setting, but not sure if I should be using that or cancellation tokens? My guess is Timeout is for the non-async/await cases?


Solution

  • As Damien said in the comments, HttpClient re-uses connections as much as possible, hence the reason why the connection is not closed on cancel.

    When canceling a request like that, the HttpClient will just stop sending/receiving data to/from the other end. It will not send anything to inform the other end that it was cancelled. So the timeout you see of 1 minute depends on the behavior of the other end of your connection.

    Also, if you want to cancel each request after 5 seconds, you can as well set the Timeout property of _httpClient to TimeSpan.FromSeconds(5). The behavior will be exactly the same (a TaskCanceledException will be thrown if the other end doesn't respond within 5 seconds).