ReadAsStreamAsync を呼び出すときに HttpResponseMessage を破棄するかどうか、またはいつ破棄するか? 質問する

ReadAsStreamAsync を呼び出すときに HttpResponseMessage を破棄するかどうか、またはいつ破棄するか? 質問する

私はSystem.Net.Http.HttpClientクライアント側の HTTP 通信を行います。HTTP はすべて 1 か所にまとめ、コードの残りの部分から抽象化しています。あるインスタンスでは、応答コンテンツをストリームとして読み取りたいのですが、ストリームのコンシューマーは、HTTP 通信が行われてストリームが開かれる場所から十分に分離されています。HTTP 通信を担当する場所では、すべてのものを破棄していますHttpClient

このユニットテストは次の時点で失敗しますAssert.IsTrue(stream.CanRead):

[TestMethod]
public async Task DebugStreamedContent()
{
    Stream stream = null; // in real life the consumer of the stream is far away 
    var client = new HttpClient();        
    client.BaseAddress = new Uri("https://www.google.com/", UriKind.Absolute);

    using (var request = new HttpRequestMessage(HttpMethod.Get, "/"))
    using (var response = await client.SendAsync(request))
    {
        response.EnsureSuccessStatusCode();
        //here I would return the stream to the caller
        stream = await response.Content.ReadAsStreamAsync();
    }

    Assert.IsTrue(stream.CanRead); // FAIL if response is disposed so is the stream
}

IDisposable通常、私はできるだけ早く何かを処分しようとしますが、この場合、 を処分すると、から返されたHttpResponseMessageも処分されます。StreamReadAsStreamAsync

したがって、呼び出しコードは、応答メッセージとストリームを認識して所有権を取得する必要があるようです。または、応答メッセージを破棄せずにファイナライザーに処理させる必要があります。どちらのオプションも適切ではないようです。

この答えを処分しないことについて述べていますHttpClientHttpRequestMessageおよび/または についてはどうでしょうかHttpResponseMessage?

何か見落としているのでしょうか? 消費コードが HTTP を認識しないようにしたいのですが、これらの未処理のオブジェクトをそのままにしておくのは長年の習慣に反します。

ベストアンサー1

したがって、呼び出しコードは、応答メッセージとストリームを認識して所有権を取得する必要があるようです。または、応答メッセージを破棄せずにファイナライザーに処理させる必要があります。どちらのオプションも適切ではないようです。

この特定のケースでは、ファイナライザーはありませんどちらHttpResponseMessageHttpRequestMessageファイナライザーを実装しません (これは良いことです)。どちらも破棄しない場合は、GC が開始されるとガベージ コレクションが行われ、その時点で基礎となるストリームへのハンドルが収集されます。

これらのオブジェクトを使用している間は、破棄しないでください。使用後は、処分するステートメントでラップする代わりに、完了したらいつでもusing明示的に呼び出すことができます。どちらの場合も、使用するコードは、基礎となる HTTP リクエストに関する知識を持つ必要はありません。Dispose

おすすめ記事