2012-05-04 18 views
3

私はこの方法を持っています実行時に処理され、返されたストリームは無効になります。応答ストリームは

私はそれをバイト配列に変換してMemoryStreamを返したり、WebClientを使用することもできますが、このアイデアはあまり好きではありません。

ありがとうございます!

+0

ランタイムはそれを破棄しません。あなたが持っている唯一の問題は、あなたがそれを処分するまで、サーバとの接続が閉じられないことです。 – Will

答えて

3

リソースリークを起こさずにストリームを安全に返す簡単な方法はありません。主な問題は、にWebResponseを配置している:暗黙的にWebResponseを閉じると応答ストリームを閉じているためにWebResponseを閉じる

public Stream Load(string term) 
{ 
    var url = CreateSearchUrl(term); 

    var webRequest = (HttpWebRequest)WebRequest.Create(url); 
    var webResponse = webRequest.GetResponse(); // whoops this doesn't get disposed! 

    return new GZipStream(webResponse.GetResponseStream(), CompressionMode.Decompress); 
} 

は、応答ストリームを閉じるよりも実際にはより重要です。

私がWebResponseをストリームに配置することを知っている唯一の方法は、WebResponse(およびGZipStream)が破棄されたときに処理されるGZipStreamの周りにデコレータを実装することです。

public void Load(string term, Action<Stream> action) 
{ 
    var url = CreateSearchUrl(term); 

    var webRequest = (HttpWebRequest)WebRequest.Create(url); 

    using (var webResponse = webRequest.GetResponse()) 
    using (var responseStream = webResponse.GetResponseStream()) 
    using (var gzipStream = new GZipStream(responseStream, CompressionMode.Decompress)) 
    { 
     action(gzipStream); 
    } 
} 

class WebResponseDisposingStream : Stream 
{ 
    private readonly WebResponse response; 
    private readonly Stream stream; 

    public WebResponseDisposingStream(WebResponse response, Stream stream) 
    { 
     if (response == null) 
      throw new ArgumentNullException("response"); 
     if (stream == null) 
      throw new ArgumentNullException("stream"); 

     this.response = response; 
     this.stream = stream; 
    } 

    public override void Close() 
    { 
     this.response.Close(); 
     this.stream.Close(); 
    } 

    // override all the methods on stream and delegate the call to this.stream 

    public override void Flush() { this.stream.Flush(); } // example delegation for Flush() 
    // ... on and on for all the other members of Stream 
} 

はおそらく、より良いアプローチは、ストリームを使用するコードは、デリゲートとして渡され、継続渡しスタイルのようになります。これは動作しますが、それはコードのかなり多くがあります

これで、発信者はストリームで何をすべきかを単に伝えます。

Load("test", stream => Console.WriteLine("Length=={0}", stream.Length)); 

最後の注意:あなたが気づいていないしている場合は、HTTPが組み込まれている圧縮のためのサポート。以下の長さがコンソールに出力されるには詳細はWikipediaを参照してください。 HttpWebRequestには、AutomaticDecompressionプロパティを使用したHTTP圧縮の組み込みサポートが組み込まれています。 HTTP圧縮を使用すると、基本的には圧縮がコードに透過的になり、HTTPツール(ブラウザ、フィドラーなど)を使用するとさらに効果的です。