2011-09-10 27 views
5

tengo este pedazo de código para hacer una petición HTTP asíncrona:Tarea fromAsync tiempo de espera

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

Funciona, pero tengo que configurar una solicitud de tiempo de espera. Intenté usar request.Timeout pero no parece hacer nada. ¿Hay alguna forma de configurar un tiempo de espera de la tarea en este código?

Editado para agregar una nueva devolución de llamada de tiempo de espera. Nuevo código:

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

Prueba con:

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

Respuesta

8

Desde el Timeout documentation:

La propiedad de tiempo de espera no tiene efecto sobre las peticiones asíncronas realizadas con el método BeginGetResponse o BeginGetRequestStream.

Esto se debe a que el marco le obliga a manejar el tiempo de espera usted mismo. Debería poder usar el example code here, excepto pasar el Task devuelto de la llamada FromAsync al método ThreadPool.RegisterWaitForSingleObject.


Editar:

Es necesario poner el registro en la tarea original, no la continuación:

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

Esto funciona para mí (si fijo la duración de tiempo de espera muy corto, y dale a esto, siempre tengo tiempo de espera apropiadamente).

+0

Cambié el código como puede ver en la pregunta, pero el tiempo de espera no funciona. Solo recibo una devolución de llamada con timedOut falso y después de eso no ocurre nada. –

+0

@David: Puse un código de trabajo ... –

+0

No puedo hacerlo funcionar. Tengo un hilo. Duerma en el método principal. ¿Podría ser este el problema? Actualicé la publicación para mostrarte el código que estoy usando para probarlo. –

Cuestiones relacionadas