2012-11-14 38 views
11

HttpListenerを使用して静的ファイルを提供しようとしていますが、これは小さなファイルでうまくいきます。ファイルサイズが大きくなると(350MBと600MBのファイルでテストされた場合)、サーバーは次の例外のいずれかを起こして停止します。

HttpListenerExceptionスレッド終了またはアプリケーション要求のためにI/O操作が中止されました、または:
HttpListenerExceptionセマフォーのタイムアウト期間が終了しましたC#で大容量のファイルを扱うHttpListener

例外を取り除き、安定した(信頼性の高い)高速な動作をさせるには、何を変更する必要がありますか?

ここでさらに詳しい説明があります。これは基本的にthis earlier questionへのフォローアップの質問です。このコードは、エフェクトを表示するためにわずかに拡張されています。コンテンツの書き方は、私の場合は64kB(うまくいけば合理的)のチャンクサイズでループしていますが、値を変更しても速度以外の違いはありませんでした。


using(FileStream fs = File.OpenRead(@"C:\test\largefile.exe")) { 

    //response is HttpListenerContext.Response... 
    response.ContentLength64 = fs.Length; 
    response.SendChunked = false; 
    response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet; 
    response.AddHeader("Content-disposition", "attachment; filename=largefile.EXE"); 

    byte[] buffer = new byte[ 64 * 1024 ]; 
    int read; 
    using(BinaryWriter bw = new BinaryWriter(response.OutputStream)) { 
     while((read = fs.Read(buffer, 0, buffer.Length)) > 0) { 
      Thread.Sleep(200); //take this out and it will not run 
      bw.Write(buffer, 0, read); 
      bw.Flush(); //seems to have no effect 
     } 

     bw.Close(); 
    } 

    response.StatusCode = (int)HttpStatusCode.OK; 
    response.StatusDescription = "OK"; 
    response.OutputStream.Close(); 
} 

私はHttpWebRequestのを使用してC#のプログラムでも、ブラウザでのダウンロードをしようとしています、それは違いはありません。

私の研究に基づいて、私はHttpListenerが実際にクライアントにコンテンツを流すことはできないと思っています。私もBinaryWriterを使い切ってストリームに直接書きました。違いはありません。基本ストリームの周りにBufferedStreamを導入しました。違いはありません。面白いことに、もしThread.Sleep(200)や少し大きめのものがループの中に導入されていれば、それは私のボックス上で動作します。しかし、私はそれが本当の解決策のために十分安定しているとは思わない。 This questionは、正しく動作させる機会がないという印象を与えます(IIS/ASP.NETに移行するだけでなく、できるだけ離れている可能性が高い)。

答えて

10

HttpListenerをどのように初期化したか他の重要な部分を私たちに示すことはありませんでした。したがって、私は、以下のいずれかであなたのコードを試してみましたが、それが

HttpListener listener = new HttpListener(); 
listener.Prefixes.Add("http://*:8080/"); 
listener.Start(); 
Task.Factory.StartNew(() => 
{ 
    while (true) 
    { 
     HttpListenerContext context = listener.GetContext(); 
     Task.Factory.StartNew((ctx) => 
     { 
      WriteFile((HttpListenerContext)ctx, @"C:\LargeFile.zip"); 
     }, context,TaskCreationOptions.LongRunning); 
    } 
},TaskCreationOptions.LongRunning); 

WriteFileを働いたThread.Sleep(200);が削除されたあなたのコードです。

完全なコードを表示したい場合は、


void WriteFile(HttpListenerContext ctx, string path) 
{ 
    var response = ctx.Response; 
    using (FileStream fs = File.OpenRead(path)) 
    { 
     string filename = Path.GetFileName(path); 
     //response is HttpListenerContext.Response... 
     response.ContentLength64 = fs.Length; 
     response.SendChunked = false; 
     response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet; 
     response.AddHeader("Content-disposition", "attachment; filename=" + filename); 

     byte[] buffer = new byte[64 * 1024]; 
     int read; 
     using (BinaryWriter bw = new BinaryWriter(response.OutputStream)) 
     { 
      while ((read = fs.Read(buffer, 0, buffer.Length)) > 0) 
      { 
       bw.Write(buffer, 0, read); 
       bw.Flush(); //seems to have no effect 
      } 

      bw.Close(); 
     } 

     response.StatusCode = (int)HttpStatusCode.OK; 
     response.StatusDescription = "OK"; 
     response.OutputStream.Close(); 
    } 
} 
+0

いやはや!私は、ちょうど明確に考えているのではなく、Hoodpenerの問題があるかもしれないと私が強迫していることを認めなければなりません。 @ L.Bは正しい軌道に乗ってくれてありがとう。基本的には、同じ方法でHttpListenerをインスタンス化しています。コードを使用してエラーを取得します。もちろん、私たちの環境内のさまざまなPCで試してみましたが、同じ効果が見られましたが、クリーンなVMマシンでは、コードと私のオリジナルの実装の両方が問題なく動作します。原因が何であるかはまだ分かっていませんが、私はAntiVirusを疑っています...あなたの助けにもう一度感謝します! – lichtalberich

+1

@ L.B。:追加のBinaryWriterを使用する利点は何ですか? –

+0

質問と比較して大きな違いは何ですか?問題と解決策を要約できますか? –

関連する問題