2011-09-10 48 views
5

我有這樣的一段代碼,使異步HTTP請求:任務fromAsync超時

public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback) 
    { 
     WebRequest request = WebRequest.Create(uri); 
     request.Proxy = null; 

     Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task => 
      { 
       WebResponse response = task.Result; 
       Stream responseStream = response.GetResponseStream(); 
       responseCallback(new RequestCallbackState(response.GetResponseStream())); 
       responseStream.Close(); 
       response.Close(); 
      }); 
    } 

它的工作原理,但我需要設置一個請求超時。我試圖使用request.Timeout,但似乎沒有做任何事情。有沒有在這段代碼中設置任務超時的方法?

編輯添加新的超時回調。 新代碼:

public static void MakeRequest(Uri uri, Action<RequestCallbackState> responseCallback) 
    { 
     WebRequest request = WebRequest.Create(uri); 
     request.Proxy = null; 

     IAsyncResult t = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null).ContinueWith(task => 
      { 
       WebResponse response = task.Result; 
       Stream responseStream = response.GetResponseStream(); 
       responseCallback(new RequestCallbackState(response.GetResponseStream())); 
       responseStream.Close(); 
       response.Close(); 
      }); 
     ThreadPool.RegisterWaitForSingleObject(t.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, 1000, true); 
    } 

    private static void TimeoutCallback(object state, bool timedOut) 
    { 
     if (timedOut) 
     { 
      Console.WriteLine("Timeout"); 
      WebRequest request = (WebRequest)state; 
      if (state != null) 
      { 
       request.Abort(); 
      } 
     } 
    } 

測試用:

HttpSocket.MakeRequest(new Uri("http://www.google.comhklhlñ"), callbackState => 
    { 
     if (callbackState.Exception != null) 
      throw callbackState.Exception; 
     Console.WriteLine(GetResponseText(callbackState.ResponseStream)); 
    }); 
Thread.Sleep(10000); 

回答

8

Timeout documentation

超時屬性對與BeginGetResponse或BeginGetRequestStream方法制成的異步請求沒有影響。

這是因爲框架迫使你自己處理超時。您應該可以使用example code here,但將FromAsync返回的Task返回給ThreadPool.RegisterWaitForSingleObject方法。


編輯:

你需要把登記的原始任務,而不是延續:

public static void MakeRequest(Uri uri, Action<Stream> responseCallback) 
{ 
    WebRequest request = WebRequest.Create(uri); 
    request.Proxy = null; 
    const int TimeoutPeriod = 1000; 

    Task<WebResponse> t = Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); 
    ThreadPool.RegisterWaitForSingleObject((t as IAsyncResult).AsyncWaitHandle, TimeoutCallback, request, TimeoutPeriod, true); 
    t.ContinueWith(task => 
    { 
     WebResponse response = task.Result; 
     Stream responseStream = response.GetResponseStream(); 
     responseCallback(response.GetResponseStream()); 
     responseStream.Close(); 
     response.Close(); 
    }); 
} 

這個工作對我來說(如果我設置超時時間很短,打這個,我總是適時超時)。

+0

我改變了代碼,就像你在問題中看到的那樣,但超時不起作用。我只收到timedOut爲false的回調,之後沒有任何反應。 –

+0

@大衛:我把一些工作代碼... –

+0

我不能讓它工作。我在主要方法中有一個thread.sleep。可能是這個問題?我更新了這篇文章,向您展示了我用來測試它的代碼。 –