1. ホーム
  2. c#

[解決済み】HttpClientとHttpClientHandlerはリクエストの間にディスポされなければならないのでしょうか?

2022-03-25 16:36:40

質問

System.Net.Http.HttpClient System.Net.Http.HttpClientHandler は、.NET Framework 4.5 で IDisposable を実装しています (via. System.Net.Http.HttpMessageInvoker ).

using 文のドキュメントに書かれています。

IDisposableオブジェクトを使用する場合、原則として、宣言と のインスタンスを作成します。

この回答 はこのパターンを使用しています。

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

しかし、マイクロソフトの最も目につく例では、このように Dispose() 明示的にも暗黙的にも。例えば

での お知らせ のコメントで、マイクロソフトの社員に質問した人がいました。

<ブロッククオート

サンプルを確認したところ、disposeを実行していないようです。 アクションを実行します。私はHttpClientのすべてのインスタンスを使用しています。 私のアプリでは、usingステートメントを使用しており、それが正しい方法だと考えています。 HttpClientはIDisposableインターフェイスを実装しているからです。私は 正しい道ですか?

彼の答えはこうだった。

一般的にはその通りですが、注意しなければならないのは .Net 4.5では、usingとasyncは混在しないので、usingとasyncは混在しない。 は "using" 文の中で "await" を使用することができます。

ちなみに、同じHttpClientは何度でも再利用可能です。 通常、常に作成/廃棄することはありません。

この質問では、HttpClientインスタンスを何回使えるかではなく、不要になった後にそれを廃棄する必要があるかどうかを尋ねています。

(更新: 実はこの2番目の段落が、@DPedenによって以下に提供されているように、答えの鍵なのです)

そこで質問なのですが

  1. 現在の実装(.NET Framework 4.5)では、HttpClientとHttpClientHandlerのインスタンスに対してDispose()を呼び出す必要があるのでしょうか?明確化:必要性とは、リソースリークやデータ破損のリスクなど、ディスポーズしないことによる悪影響があるかどうかという意味です。

  2. 必要ないのであれば、IDisposableを実装しているので、とりあえず"good practice"になるのでしょうか?

  3. 必要(または推奨)である場合、それは このコード は、それを安全に実装していますか(.NET Framework 4.5の場合)?

  4. これらのクラスが Dispose() を呼び出す必要がないのであれば、なぜ IDisposable として実装されたのでしょうか?

  5. もしそれが必要なら、あるいは推奨されるプラクティスなら、Microsoft の例は誤解を招いたり安全でなかったりしますか?

どのように解決するのですか?

一般的なコンセンサスは、HttpClient を破棄する必要はない(はず)、というものです。

その仕組みに深く関わっている多くの人が、このように発言しています。

参照 ダレル・ミラーのブログ記事 と関連するSOの記事です。 HttpClientのクローリングでメモリリーク発生 を参考にしてください。

を読むことを強くお勧めします。 のHttpClientの章をご覧ください。 ASP.NETで進化するWebAPIをデザインする 特に、ここで引用されている "Lifecycle" のセクションは、ボンネットの下で何が起こっているのかについてのコンテキストを提供しています。

<ブロッククオート

HttpClientはIDisposableを間接的に実装していますが インターフェイスを使用しますが、HttpClientの標準的な使用法は、それを廃棄することではありません。 を使用します。HttpClient オブジェクトは、以下の期間、使用されます。 アプリケーションがHTTPリクエストを行う必要がある限り。オブジェクトを持つこと 複数のリクエストにまたがって存在することで DefaultRequestHeadersを再指定する必要がありません。 のように、リクエストごとにCredentialCacheやCookieContainerのように は、HttpWebRequest で必要でした。

DotPeekを開くのもいい。