一尘不染

是否必须在请求之间放置HttpClient和HttpClientHandler?

c#

.NET Framework
4.5中的System.Net.Http.HttpClientSystem.Net.Http.HttpClientHandler实现IDisposable(通过System.Net.Http.HttpMessageInvoker)。

using声明文件说:

通常,使用IDisposable对象时,应在using语句中声明并实例化它。

此答案使用以下模式:

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();
}

但是Microsoft最明显的示例都没有Dispose()显式或隐式调用。例如:

公告的评论中,有人问微软员工:

检查样本后,我发现您没有对HttpClient实例执行dispose操作。我已经在我的应用程序上使用了using语句来使用HttpClient的所有实例,并且我认为这是自HttpClient实现IDisposable接口以来的正确方法。我在正确的道路上吗?

他的回答是:

通常,这是正确的,尽管您必须谨慎使用“使用”和异步,因为它们并没有真正混入.Net 4中。在.Net 4.5中,您可以在“ using”语句中使用“
await”。

顺便说一句,您可以根据需要多次重复使用同一HttpClient,因此通常不会一直创建/处置它们。

第二段对于该问题是多余的,它与您可以使用HttpClient实例的次数无关,而与不再需要它之后是否需要处置它有关。

(更新:实际上,第二段是答案的关键,如@DPeden所提供。)

所以我的问题是:

  1. 在当前实现(.NET Framework 4.5)的情况下,是否有必要在HttpClient和HttpClientHandler实例上调用Dispose()?澄清:“必要”是指是否存在不处置的任何负面后果,例如资源泄漏或数据损坏风险。

  2. 如果没有必要,因为它们实现了IDisposable,这是否仍然是“良好实践”?

  3. 如果有必要(或建议),上述代码是否可以安全地实现(对于.NET Framework 4.5)?

  4. 如果这些类不需要调用Dispose(),为什么将它们实现为IDisposable?

  5. 如果他们有要求,或者如果推荐这样做,Microsoft的示例是否会引起误解或不安全?


阅读 426

收藏
2020-05-19

共1个答案

一尘不染

普遍的共识是您不需要(不应)处置HttpClient。

许多与它的工作方式密切相关的人都说过这一点。

请参阅Darrel Miller的博客文章和相关的SO文章:HttpClient爬网导致内存泄漏,以供参考。

我也强烈建议您阅读使用ASP.NET设计可演化的Web
API》中

的HttpClient一章,


了解有关
幕后

情况的上下文,尤其是此处引用的“生命周期”部分:

尽管HttpClient确实间接实现了IDisposable接口,但是HttpClient的标准用法是在每次请求后都不要处理它。只要您的应用程序需要发出HTTP请求,HttpClient对象就可以存在。在多个请求中都存在一个对象,这为设置DefaultRequestHeaders提供了空间,并且使您不必在HttpWebRequest所必需的每个请求上重新指定诸如CredentialCache和CookieContainer之类的东西。

甚至开放DotPeek。

2020-05-19