【发布时间】:2013-03-20 06:19:37
【问题描述】:
System.Net.Http.HttpClient 和 System.Net.Http.HttpClientHandler 在 .NET Framework 4.5 中实现 IDisposable(通过 System.Net.Http.HttpMessageInvoker)。
using 声明文档说:
通常,当您使用 IDisposable 对象时,您应该声明并 在 using 语句中实例化它。
This answer 使用这种模式:
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()。例如:
- original blog article 宣布发布 HttpClient。
- HttpClient 的实际MSDN documentation。
- BingTranslateSample
- GoogleMapsSample
- WorldBankSample
在announcement的cmets中,有人问微软员工:
检查您的样品后,我发现您没有执行处置 对 HttpClient 实例的操作。我已经使用了 HttpClient 的所有实例 在我的应用程序上使用 using 声明,我认为这是正确的方法 因为 HttpClient 实现了 IDisposable 接口。我在吗 正确的道路?
他的回答是:
一般来说这是正确的,尽管你必须小心 “使用”和异步,因为它们并没有真正混合在 .Net 4 中,在 .Net 4.5 中你 可以在“using”语句中使用“await”。
顺便说一句,您可以根据自己的喜好多次重复使用相同的 HttpClient 通常您不会一直创建/处置它们。
第二段对于这个问题是多余的,它不是关心你可以使用多少次HttpClient实例,而是关心在你不再需要它之后是否需要释放它。
(更新:事实上,第二段是答案的关键,@DPeden 在下面提供。)
所以我的问题是:
考虑到当前的实现 (.NET Framework 4.5),是否有必要在 HttpClient 和 HttpClientHandler 实例上调用 Dispose()?澄清:“必要”是指不处置是否有任何负面后果,例如资源泄漏或数据损坏风险。
如果没有必要,由于他们实现了 IDisposable,这是否是一种“好习惯”?
如果有必要(或推荐),上面提到的this code 是否安全地实现它(对于 .NET Framework 4.5)?
如果这些类不需要调用 Dispose(),为什么它们被实现为 IDisposable?
如果他们需要,或者如果这是推荐做法,Microsoft 示例是否具有误导性或不安全?
【问题讨论】:
-
@Damien_The_Unbeliever,感谢您的反馈。你对我如何澄清这个问题有什么建议吗?我想知道它是否会导致通常与不处置资源相关的问题,例如资源泄漏和数据损坏。
-
@Damien_The_Unbeliever:不正确。特别是,流编写器必须具备正确的行为。
-
@StephenCleary - 您在考虑哪些方面?当然,您可以在每次写入后调用
Flush,除了它继续持有底层资源超过必要的时间带来不便之外,“正确行为”所需的什么不会发生? -
这是完全错误的:“通常,当您使用 IDisposable 对象时,您应该在 using 语句中声明和实例化它”。在决定是否应该使用 using 之前,我总是会阅读有关实现 IDisposable 的类的文档。作为我实现 IDisposable 的库的作者,因为需要释放未管理的资源,如果消费者每次都创建处置实例而不是重新使用现有实例,我会感到震惊。这并不是说最终不要处理实例..
-
我已经向微软提交了一个 PR 来更新他们的文档:github.com/dotnet/docs/pull/2470
标签: c# .net-4.5 idisposable using dotnet-httpclient