2012-03-21 4 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 메서드를 취소 할 수있는 방법이 있습니까? 아니면 더 나은 접근 방법을 사용해야합니까? @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 무한 대기 시간을 방지하기 위해 제한 시간을 원하지만 비동기가 좋은 방법이지만 문제는 없습니다 – dcarneiro

답변

-1

나는 Nomad101 제안을 사용하여 끝내고 try/catch로 읽기를 둘러 쌉니다.

2

당신이 타임 아웃 경우를 얻으려고 노력하는 경우 당신은 웹 서버를받지 못하고 답을 얻지 못한다. 잘못된 위치에서 그것을하려고한다.

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

webservice에서 응답을 받지만이 특정 요청은 .GetResponseStream() 메서드를 사용하고 .GetResponse() 메서드 나 .BeginGetResponse() 메서드를 사용하는 대신 Stream에 대한 것입니다. 적어도 첫 번째 stream.Read()를 성공으로 수행 할 수 있습니다. 때로는 두 번째 또는 다음 읽기 중 하나가 시간 초과를 가져옵니다. – dcarneiro

+0

수업을 사용하는 코드를 보여줄 수 있습니까? – JotaBe

+0

해당 정보로 질문을 업데이트했습니다. – dcarneiro