213

In all the examples I can find of usages of HttpClient, it is used for one off calls. But what if I have a persistent client situation, where several requests can be made concurrently? Basically, is it safe to call client.PostAsync on 2 threads at once against the same instance of HttpClient.

I am not really looking for experimental results here. As a working example could simply be a fluke (and a persistent one at that), and a failing example can be a misconfiguration issue. Ideally I'm looking for some authoritative answer to the question of concurrency handling in HttpClient.

1

3 Answers 3

217

According to Microsoft Docs, since .NET 4.5 The following instance methods are thread safe (thanks @ischell):

CancelPendingRequests DeleteAsync GetAsync GetByteArrayAsync GetStreamAsync GetStringAsync PostAsync PutAsync SendAsync 
Sign up to request clarification or add additional context in comments.

15 Comments

Yeah, I wasn't sure about that one, as it appears to be a standard warning on everything on MSDN (and I remember reading some MSDN blogs about how sometime that warning is wrong, as it is applied blindly to everything).
This is wrong; in the remarks section of the MSDN page you linked, it says that GetAsync, PostAsync, etc. are all thread safe.
@ischell: I can assure you that the paragraph in question was not there at the time this issue was discussed.
So Microsoft have designed HttpClient to be reusable but then the class has instance data for headers: client.DefaultRequestHeaders.Accept.Add(...);
In late, but I wanted to comment on @cwills. DefaultRequestHeaders are just that, defaults. If you want different headers on a per-request-basis, you can create new StringContent(), set additional headers on that, then use the overload that takes URI and HttpContent.
|
108

Here is another article from Henrik F. Nielsen about HttpClient where he says:

"The default HttpClient is the simplest way in which you can start sending requests. A single HttpClient can be used to send as many HTTP requests as you want concurrently so in many scenarios you can just create one HttpClient and then use that for all your requests."

10 Comments

What about if the username and password can change in between threads? that's what i can't seem to find anyone talking about
@NicholasDiPiazza: how often does it change? If there's a known set of user/password pairs then you can create a pool of HttpClient instances.
Note that reusing the same HttpClient for all your requests might result in stale DNS issues: github.com/dotnet/corefx/issues/11224.
@OhadSchneider If believe that issue is limited to .net core. You can fix the issue with .net 4 by injecting a custom HttpClientHandler into the HttpClient constructor then setting the "ConnectionLeaseTimeout". However, if no requests are sent to the endpoint for 100 seconds the connection will refresh on its own. protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,CancellationToken cancellationToken) { var sp = ServicePointManager.FindServicePoint(request.RequestUri); sp.ConnectionLeaseTimeout = 100 * 1000; }
@xr280xr simple answer: yes, disposing it will quickly exhaust your TCP sockets under load. Long answer: it's complex, and no one really knows the right way to use it. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong stackoverflow.com/a/15708633/825588 nimaara.com/beware-of-the-net-httpclient learn.microsoft.com/en-us/azure/architecture/antipatterns/…
|
23

Found one MSDN forum post by Henrik F. Nielsen (one of HttpClient's principal Architects).

Quick summary:

  • If you have requests that are related (or won't step on eachother) then using the same HttpClient makes a lot of sense.

  • In genral I would recommend reusing HttpClient instances as much as possible.

1 Comment

One important thing to consider for reusability: do fundamental settings of the client such as the timeout change in between calls? In my case, I refactored my code to reuse HttpClients a lot, only to find out the user may no longer update the custom timeout value in my app's settings, because after the first request was made you can no longer adjust the Timeout property. That wasn't an issue when I was creating new clients with the current timeout value from the settings.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.