Search code examples
c#.net.net-coredotnet-httpclient

Should I dispose HttpClient in C# when I am creating instance for every request?


There are many resources asking to re-use HttpClient instances to avoid socket exhaustion. In that approach, one should not dispose the HttpClient instances.

But similar to the ask in the first comment in this answer asks:

would it be correct to say that "you do not need to dispose of HttpClient IF YOU HOLD ON TO THE INSTANCE TO REUSE IT LATER"? For instance, if a method is called repeatedly and creates a new HttpClient instance (even though it's not the recommended pattern in most cases), would it still be correct to say this method should not dispose the instance (that will not be reused)? It could lead to thousands of undisposed instances.

I want to know if I should dispose using the using keyword, in an app that does not follow the pattern, and creates instances for every request.

Please do not recommend to change the design to re-use, because that will be done in due time, but suggest what is the proper way to use when the creation happens for each request.

For .NET Core.


Solution

  • Whenever you use using for an HttpClient instance the following things happen:

    • HttpClient cancels all the pending requests via a CancellationToken. Ref
    • HttpMessageInvoker (the base class of the HttpClient) disposes the underlying HttpMessageHandler. Ref
      • HttpMessageHandler is an abstract class, there are many implementation classes like SocketsHttpHandler, HttpClientHandler, etc. Ref
      • Whenever you allocate a new HttpClient then you use the HttpClientHandler. Ref
    • HttpClientHandler disposes its underlying HttpHandlerType. Ref
      • Which is either a BrowserHttpHandler or a SocketsHttpHandler. Ref
    • The SocketsHttpHandler disposes its underlying HttpMessageHandlerStage. Ref
      • This stage object holds a reference for a chain of handlers.
      • Depending on your settings, the chain could contain very different handlers
      • The innermost handler is either the HttpAuthenticatedConnectionHandler or the HttpConnectionHandler
    • In both connection handler cases they dispose their HttpConnectionPoolManager Ref
    • HttpConnectionPoolManager disposes several timers, HttpConnectionPool Ref and unsubscribes from the NetworkChange.NetworkAddressChanged event Ref
    • HttpConnectionPool does a lots of cleanup and it is HTTP protocol version aware. Ref
    • ...

    I stop here, because of the following reasons:

    • SocketsHttpClientHandler is the lowest public class that you can interact with directly. All the lower layers are internal so they are just implementation details.
    • As you can see that HttpClient dispose chain not just simply cancels the pending requests it does a lot of things.

    So, cleaning up stuff after you are done with the usage of the HttpClient is a better option IMHO than waiting for the GC to do it for you when it triggers.