Problem
In.NET Framework 4.5, System.Net.Http.HttpClient and System.Net.Http.HttpClientHandler implement IDisposable (via System.Net.Http.HttpMessageInvoker).
According to the documentation on the using statement:
This pattern is used in this response:
var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("foo", "bar"),
new KeyValuePair<string, string>("baz", "bazinga"),
});
cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
var result = client.PostAsync("/test", content).Result;
result.EnsureSuccessStatusCode();
}
However, Microsoft’s most visible instances do not use Dispose(), either directly or implicitly. Consider the following example:
Someone asked the Microsoft employee in the comments section of the announcement:
His answer was:
The second paragraph is irrelevant to our subject, which is concerned with whether or not it is essential to dispose of a HttpClient instance after it has served its purpose.
(Update: as @DPeden points out below, the second paragraph provides the key to the answer.)
So here are my inquiries:
Asked by Fernando Correia
Solution #1
The broad agreement is that HttpClient does not (should not) need to be disposed of.
This has been stated by a number of people who are closely familiar with how it operates.
For further information, see Darrel Miller’s blog post and a linked SO post: HttpClient crawling causes memory leak.
I’d also recommend reading the HttpClient chapter from Designing Evolvable Web APIs with ASP.NET for a better understanding of what’s going on behind the scenes, especially the “Lifecycle” section referenced here:
Alternatively, you might use DotPeek.
Answered by David Peden
Solution #2
The current responses are a little perplexing and misleading, as they leave out certain crucial DNS consequences. I’ll try to give a clear picture of where things stand.
Answered by Ohad Schneider
Solution #3
The new best approach to manage HttpClient and HttpClientHandler in.NET Core >=2.1 and.NET 5.0+ is to use HttpClientFactory, which no one seems to have noticed yet.
It cleanly and intuitively resolves the majority of the aforementioned concerns and pitfalls. From Steve Gordon’s excellent blog:
To your.Net Core (2.1.1 or later) project, add the following packages:
Microsoft.AspNetCore.All
Microsoft.Extensions.Http
Add the following to Startup.cs:
services.AddHttpClient();
Inject and use:
[Route("api/[controller]")]
public class ValuesController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
public ValuesController(IHttpClientFactory httpClientFactory)
{
_httpClientFactory = httpClientFactory;
}
[HttpGet]
public async Task<ActionResult> Get()
{
var client = _httpClientFactory.CreateClient();
var result = await client.GetStringAsync("http://www.google.com");
return Ok(result);
}
}
More features can be found in Steve’s blog’s series of entries.
Answered by pcdev
Solution #4
Calling Dispose(), in my opinion, is only important when locking resources that you will need later (like a particular connection). It’s usually a good idea to give up resources you’re no longer utilizing, even if you won’t need them again, because you shouldn’t keep things you don’t need (pun intended).
The Microsoft example isn’t necessarily incorrect. When the application is closed, all resources used will be freed. And in that scenario, it happens nearly quickly after the HttpClient has completed its task. In similar situations, invoking Dispose() directly isn’t necessary.
When a class implements IDisposable, however, the expectation is that you should Dispose() of its instances as soon as you’re ready and able. I’d argue that this is especially true in scenarios like HttpClient, where it’s not clear whether resources or connections are being kept onto/opened. If the connection will be reused [soon], you’ll want to avoid Dipose()ing it because you’re not “completely ready” in that scenario.
Also see IDisposable. When to Call and How to Dispose Dispose
Answered by svidgen
Solution #5
Short answer: “The widespread agreement is that you do not (should not) need to dispose of HttpClient,” as stated in the already acceptable answer, is incorrect.
Long answer: BOTH of the following assertions are correct and possible to achieve at the same time:
AND THEY DO NOT HAVE TO BE IN COMPATIBILITY WITH EACH OTHER. It’s simply an issue of how you organize your code to reuse a HttpClient while also correctly disposing of it.
An even longer response, taken from another of my responses:
It’s not a coincidence that some blog postings blame the IDisposable interface of HttpClient for making people employ the using (var client = new HttpClient())… pattern, which leads to the exhausted socket handler problem.
That, I believe, stems from an underlying (mis?) belief that “an IDisposable object is meant to be short-lived.”
HOWEVER, while it appears to be a transient phenomenon when we write code in this way
using (var foo = new SomeDisposableObject())
{
...
}
IDisposable objects do not have to be short-lived, according to the official documentation. IDisposable is, by definition, just a means for releasing unmanaged resources. There’s nothing else. In that sense, you are EXPECTED to trigger the disposal at some point, but it is not required that you do so immediately.
As a result, it’s up to you to decide when to start the disposal process based on the life cycle requirements of your actual object. Nothing prevents you from using an IDisposable in a long-term manner:
using System;
namespace HelloWorld
{
class Hello
{
static void Main()
{
Console.WriteLine("Hello World!");
using (var client = new HttpClient())
{
for (...) { ... } // A really long loop
// Or you may even somehow start a daemon here
}
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
}
With this new understanding, we can plainly see that the “fix” initializes HttpClient once but never disposes of it, which is why the connection stays in the ESTABLISHED state in its netstat report, indicating that it has not been properly closed. If it was closed, it would be in the TIME WAIT state. In practice, having only one connection open after your entire application has finished isn’t a major concern, and the blog poster still sees a performance boost after the change; but, blaming IDisposable and choosing not to discard it is conceptually incorrect.
Answered by RayLuo
Post is based on https://stackoverflow.com/questions/15705092/do-httpclient-and-httpclienthandler-have-to-be-disposed-between-requests