システム.Net.Http.HttpClientそしてSystem.Net.Http.HttpClientHandler.NET Framework 4.5では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 のリリースを発表します。
- 実際のMSDNドキュメントHttpClient 用。
- BingTranslateサンプル
- Googleマップサンプル
- 世界銀行サンプル
の中に発表のコメントについて、誰かがマイクロソフトの従業員に質問しました。
サンプルを確認したところ、HttpClient インスタンスで dispose アクションが実行されていないことがわかりました。アプリでは、using ステートメントを使用して HttpClient のすべてのインスタンスを使用しており、HttpClient は IDisposable インターフェイスを実装しているため、これが正しい方法だと思いました。正しい方向に進んでいるでしょうか?
彼の答えはこうでした。
一般的にはそれは正しいですが、.Net 4 では「using」と async は実際には混在しないので注意が必要です。.Net 4.5 では、「using」ステートメント内で「await」を使用できます。
ちなみに、同じ HttpClient を何度でも再利用できるので、通常は頻繁に作成/破棄する必要はありません。
2 番目の段落はこの質問には不必要です。この質問は、HttpClient インスタンスを何回使用できるかではなく、不要になった後に破棄する必要があるかどうかに関するものです。
(更新: 実際、@DPeden が以下で提供しているように、2 番目の段落が答えの鍵となります。)
私の質問は次のとおりです:
現在の実装 (.NET Framework 4.5) では、HttpClient および HttpClientHandler インスタンスで Dispose() を呼び出す必要がありますか? 説明: 「必要」とは、破棄しないことでリソース漏洩やデータ破損のリスクなど、悪影響が生じる可能性があることを意味します。
必要でない場合は、IDisposable を実装しているので、とにかく「良い方法」になるでしょうか?
必要(または推奨)であれば、このコード上記で述べたように、これを安全に実装できますか (.NET Framework 4.5 の場合)?
これらのクラスで Dispose() を呼び出す必要がない場合、なぜ IDisposable として実装されたのでしょうか?
要求されている場合、または推奨されている場合、Microsoft の例は誤解を招くもの、または安全でないものですか?
ベストアンサー1
一般的な合意としては、HttpClient を破棄する必要はない (すべきではない) ということです。
その仕組みに深く関わっている多くの人々が、このことを述べています。
見るダレル・ミラーのブログ投稿関連するSOの投稿:HttpClient のクロールによりメモリ リークが発生する参考のため。
また、ぜひ読んでみてくださいASP.NET による進化型 Web API の設計の HttpClient の章内部で何が起こっているか、特にここで引用した「ライフサイクル」セクションのコンテキストについては、以下を参照してください。
HttpClient は間接的に IDisposable インターフェイスを実装していますが、HttpClient の標準的な使用法では、要求のたびにそれを破棄するわけではありません。HttpClient オブジェクトは、アプリケーションが HTTP 要求を行う必要がある限り存続するように設計されています。オブジェクトが複数の要求にわたって存在すると、DefaultRequestHeaders を設定するための場所が有効になり、HttpWebRequest で必要だったように、要求ごとに CredentialCache や CookieContainer などを再指定する必要がなくなります。
あるいは、DotPeek を開いてみることもできます。