2012-05-12 42 views
16

Me pregunto si hay una manera fácil de obtener la respuesta de una httpwebrequest asincrónica.Obtener la respuesta de un HttpWebRequest asíncrono

Ya he visto esta pregunta here pero todo lo que intento hacer es devolver la respuesta (que suele ser json o xml) en forma de cadena a otro método donde puedo analizarlo/tratarlo en consecuencia.

Heres algo de código:

tengo estos dos métodos estáticos aquí que creo que es seguro para subprocesos como todos los params se pasan y no hay variables locales compartidos que utilizan los métodos?

public static void MakeAsyncRequest(string url, string contentType) 
{ 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
    request.ContentType = contentType; 
    request.Method = WebRequestMethods.Http.Get; 
    request.Timeout = 20000; 
    request.Proxy = null; 

    request.BeginGetResponse(new AsyncCallback(ReadCallback), request); 
} 

private static void ReadCallback(IAsyncResult asyncResult) 
{ 
    HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState; 
    try 
    { 
     using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult)) 
     { 
      Stream responseStream = response.GetResponseStream(); 
      using (StreamReader sr = new StreamReader(responseStream)) 
      { 
       //Need to return this response 
       string strContent = sr.ReadToEnd(); 
      } 
     } 
     manualResetEvent.Set(); 
    } 
    catch (Exception ex) 
    { 
     throw ex; 
    } 
} 
+0

El código que envió trabajado bien una vez me quita el ManualResetEvent extraña.Conjunto(); - ¿Cuál es el problema que estás teniendo? –

+0

@JamesManning Hola, eso fue un error tipográfico, estoy buscando una forma más fácil de obtener el resultado. Lo que ha proporcionado (Tarea ) está exactamente en línea. Acabo de dar el salto de solicitudes sincrónicas, parece que hay mucho más en juego. Gracias – gdp

Respuesta

38

Suponiendo que el problema es que está teniendo dificultades para obtener el contenido devuelto, la ruta más fácil probablemente sería usar async/await si puede usarlo. Incluso mejor sería cambiar a HttpClient si está utilizando .NET 4.5 ya que es 'nativamente' asíncrono.

Con .NET 4 y C# 4, puede utilizar Tarea para envolverlos y facilitar el acceso al resultado final. Por ejemplo, una opción sería la siguiente. Tenga en cuenta que tiene el método principal de bloqueo hasta que la cadena de contenido esté disponible, pero en un escenario "real" es probable que pase la tarea a otra cosa o que encierre otra ContinueCon sin ella o lo que sea.

void Main() 
{ 
    var task = MakeAsyncRequest("http://www.google.com", "text/html"); 
    Console.WriteLine ("Got response of {0}", task.Result); 
} 

// Define other methods and classes here 
public static Task<string> MakeAsyncRequest(string url, string contentType) 
{ 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
    request.ContentType = contentType; 
    request.Method = WebRequestMethods.Http.Get; 
    request.Timeout = 20000; 
    request.Proxy = null; 

    Task<WebResponse> task = Task.Factory.FromAsync(
     request.BeginGetResponse, 
     asyncResult => request.EndGetResponse(asyncResult), 
     (object)null); 

    return task.ContinueWith(t => ReadStreamFromResponse(t.Result)); 
} 

private static string ReadStreamFromResponse(WebResponse response) 
{ 
    using (Stream responseStream = response.GetResponseStream()) 
    using (StreamReader sr = new StreamReader(responseStream)) 
    { 
     //Need to return this response 
     string strContent = sr.ReadToEnd(); 
     return strContent; 
    } 
} 
+0

Gracias de nuevo por su respuesta y tiempo. – gdp

+0

Una pregunta rápida, al acceder a los métodos de MakeAsyncRequest() Resultado de la propiedad, ¿cómo puedo asegurarme de que el resultado esté siempre terminado cuando intento usar la respuesta? – gdp

+0

La propiedad del resultado se bloqueará hasta que esté lista, si no lo está. –

2

Una vez que se vuelve asincrónico, nunca se puede regresar. Desde allí solo tienes acceso a la devolución de llamada de la asincrónica. puede aumentar la complejidad de esto y hacer algunos threading & waithandles, pero eso puede ser un esfuerzo bastante doloroso.

Técnicamente, también puede dejar el hilo cuando necesita esperar los resultados, pero no lo recomiendo, también puede hacer una solicitud http normal en ese momento.

En C# 5 tienen comandos asincrónicos/de espera que facilitarán la obtención de los resultados de la llamada asincrónica al hilo principal.

+0

el hilo es lo que tengo que entender. Gracias por tu contribución. – gdp

5

"Aún mejor sería cambiar a HttpClient si está utilizando .NET 4.5, ya que es 'nativa' asíncrono". - respuesta absolutamente correcta por James Manning. Esta pregunta fue hecha hace aproximadamente 2 años. Ahora tenemos .NET framework 4.5, que proporciona métodos asincrónicos potentes. Use HttpClient. Considere el siguiente código:

async Task<string> HttpGetAsync(string URI) 
    { 
     try 
     { 
      HttpClient hc = new HttpClient(); 
      Task<Stream> result = hc.GetStreamAsync(URI); 

      Stream vs = await result; 
      StreamReader am = new StreamReader(vs); 

      return await am.ReadToEndAsync(); 
     } 
     catch (WebException ex) 
     { 
      switch (ex.Status) 
      { 
       case WebExceptionStatus.NameResolutionFailure: 
        MessageBox.Show("domain_not_found", "ERROR", 
        MessageBoxButtons.OK, MessageBoxIcon.Error); 
       break; 
        //Catch other exceptions here 
      } 
     } 
    } 

Para utilizar HttpGetAsync(), hacer un nuevo método que es "asíncrono" también. Se requiere asíncrono, porque tenemos que utilizar "a la espera" en GetWebPage() Método:

async void GetWebPage(string URI) 
     { 
      string html = await HttpGetAsync(URI); 
      //Do other operations with html code 
     } 

Ahora bien, si desea obtener página web el código fuente HTML de forma asíncrona, sólo llame GetWebPage ("dirección web ... "). Incluso la lectura de Stream es asincrónica.

NOTA: para utilizar HttpClient .NET framework 4.5 es necesario. También debe agregar la referencia System.Net.Http en su proyecto y agregar también "using System.Net.Http" para acceder fácilmente.

Para leer con más detalle cómo funciona este enfoque, visite: http://msdn.microsoft.com/en-us/library/hh191443(v=vs.110).aspx

El uso de asíncrono: Async in 4.5: Worth the Await

Cuestiones relacionadas