2011-09-10 10 views
5

Mam ten fragment kodu, aby asynchronicznego żądania HTTP:Zadanie fromAsync Timeout

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(); 
      }); 
    } 

to działa, ale muszę ustawić limit czasu żądania się. Próbowałem użyć request.Timeout, ale nic nie robię. Czy istnieje sposób na ustawienie limitu czasu zadania w tym kodzie?

Edytowane w celu dodania nowego wywołania zwrotnego z limitem czasu. Nowy kod:

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(); 
      } 
     } 
    } 

Testowanie z:

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

Odpowiedz

8

Z Timeout documentation:

Właściwość Timeout nie ma wpływu na asynchronicznych żądań wykonanych metodą BeginGetResponse lub BeginGetRequestStream.

Dzieje się tak dlatego, że ramy zmuszają do samodzielnego radzenia sobie z limitem czasu. Powinieneś być w stanie użyć example code here, z wyjątkiem przekazania Task zwróconego z połączenia FromAsync do metody .


Edit:

Musisz umieścić rejestrację na oryginalnym zadaniu, a nie kontynuacja:

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(); 
    }); 
} 

Działa to dla mnie (jeśli mogę ustawić długość czasu oczekiwania bardzo krótki, a uderz w to, zawsze odpowiednio timeout).

+0

Zmieniłem kod, jak widać w pytaniu, ale limit czasu nie działa. Otrzymuję tylko wywołanie zwrotne z timedOut false, a po tym czasie nic się nie dzieje. –

+0

@David: Wprowadziłem trochę działającego kodu ... –

+0

Nie mogę sprawić, żeby działało. Mam wątek.sleep w głównej metody. Czy to może być problem? Zaktualizowałem wpis, aby pokazać kod, którego używam do przetestowania go. –