2012-03-21 23 views
3

私はデータを読み取っているHttpWebResponse.GetResponseStream()からストリームを取得しています。 今度はTimeoutプロパティを実装したいと思います。これを行う最も簡単な方法はstream.ReadTimeout = timeoutですが、InvalidOperationException -> Timeouts are not supported on this streamがスローされます。ストリームの読み取り時にタイムアウトプロパティを実装する

これを考えると、自分自身でtimeoutプロパティを実装しようとしていますが、disposeに固執しています。このコードで

public class MyStream : Stream { 
    private readonly Stream _src; 
    public override int ReadTimeout { get; set; } 

    public MyStream (Stream src, int timeout) { 
     ReadTimeout = timeout; 
     _src = src; 
    } 

    public override int Read(byte[] buffer, int offset, int count) { 
     var timer = new AutoResetEvent(false); 
     int read = 0; 

     ThreadPool.QueueUserWorkItem(
      _ => { 
       read = _src.Read(buffer, offset, count); 
       timer.Set(); 
      }); 
     bool completed = timer.WaitOne(ReadTimeout); 
     if (completed) { 
      return read; 
     } 
     throw new TimeoutException(string.Format("waited {0} miliseconds", ReadTimeout)); 
    } 

問題がされた後で適切にどこかで処理されているTimeoutExceptionがスローされます。これは私がこれまでに得たものです。 _srcストリームが破棄されたことを示す_src.Read(buffer, offset, count)の例外がスローされます。

ThreadPoolメソッドをキャンセルする方法はありますか?より良いアプローチとどちらを使用する必要がありますか?

おかげ

EDIT

@JotaBeで尋ねたように、私はHttpWebResponseのからのストリームを取得するコードですた。

_httpRequest = WebRequest.CreateHttp(url); 

_httpRequest.AllowReadStreamBuffering = false; 
_httpRequest.BeginGetResponse(
    result => 
     { 
      try { 
       _httpResponse = (HttpWebResponse)_httpRequest.EndGetResponse(result); 
       stream = _httpResponse.GetResponseStream(); 
      } 
      catch (WebException) { 
       downloadCompleted.Set(); 
       Abort(); 
      } 
      finally { 
       downloadCompleted.Set(); 
      } 
     }, 
     null); 

    bool completed = downloadCompleted.WaitOne(15 * 1000); 
    if (completed) { 
     return new MyStream(stream, 10000); 
    } 
+1

['Stream.BeginRead'](http://msdn.microsoft.com/en-us/library/system.io.stream.beginread(v = vs.95).aspx )、 'IAsyncResult'の' AsyncWaitHandle'プロパティを使って手を動かすのではなく、それを待ってください。 – vcsjones

+0

あなたがこの道をあまり遠く離れておらず、代替手段を探求していれば、私はReactive Extensions(Rx)を使用することでこの種のことを自明にしていることが分かりました。 codeplexにWP7Contribプロジェクトもあります。それはあなたが活用できるRxに基づくすべてのネットワーク通信の側面を持っています。 – Alex

+0

@vcsjones無限の待ち時間を防ぐためにタイムアウトしたいのですが、asyncは良い習慣ですが、ここでは問題はありません – dcarneiro

答えて

-1

私はNomad101の提案を使用して終了し、try/catchで読み込みを囲みます。

2

あなたがあればタイムアウトを取得しようとしている場合Webサーバーからフォームを受信して​​応答しないと、間違った場所で実行しようとしています。

HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 

これがタイムアウトすることができます操作です:

が応答を取得するには、通常、要求を行います。非同期パターンの開始/終了を使用して、別の方法で呼び出す必要があります。

本の完全な例は、この例では、コールバック関数を使用しています MSDN doc for HttpWebRequest.BeginGetResponse Method

です。ただし、Begin/Endを使用する方法はさまざまです。たとえば、次のようにIAsyncResultでWaitHandleを使用できます。

IAsyncResult ar = req.BeginGetResponse(yourCallback, null); 
bool completed = ar.AsyncWaitHandle.WaitOne(15000 /*your timeout in miliseconds*/); 

これは15秒間待機します。それ以前に応答が到着すれば、完了します。そうでない場合、完了は偽になります。次に、HttpWebRequest.Abort()メソッドを使用して要求を中止することができます。

Begin/Endパターンは、必要なスレッドの管理を担当します。

+0

ウェブサービスからの回答が届きましたが、この特定のリクエストはストリーム用です.GetResponse()メソッドや.BeginGetResponse()メソッドを使用する代わりに、私は.GetResponseStream()メソッドを使用しています。少なくとも最初のstream.Read()を成功させることができます。ときには、次の読み込みの2番目または1つで、タイムアウトが得られます。 – dcarneiro

+0

あなたのクラスを使用するコードを教えてもらえますか? – JotaBe

+0

この情報で質問を更新しました – dcarneiro

関連する問題