2012-05-12 10 views
16

Mi chiedo se c'è un modo semplice per ottenere la risposta di un httpwebrequest asincrono.Ottenere la risposta di un HttpWebRequest asincrono

Ho già visto questa domanda here ma tutto quello che sto cercando di fare è restituire la risposta (che di solito è json o xml) sotto forma di stringa ad un altro metodo in cui posso quindi analizzarlo/gestirlo di conseguenza.

Heres po 'di codice:

ho questi due metodi statici qui che secondo me sono thread-safe come tutte le params sono passati e non ci sono variabili locali condivisi che utilizzano i metodi?

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

Il codice che hai postato lavorato bene una volta ho rimosso il ManualResetEvent estranea.Impostato(); - qual è il problema che stai avendo? –

+0

@JamesManning Ciao sì che era un errore di battitura, io sono dopo un modo più semplice per ottenere il risultato. Quello che hai fornito (compito ) è esattamente in linea con le linee. Ho appena fatto il salto da richieste sincrone, sembra che ci sia molto di più in corso. Grazie – gdp

risposta

38

Supponendo che si stia riscontrando difficoltà nel raggiungere il contenuto restituito, il percorso più semplice probabilmente utilizzerà async/attendi se è possibile utilizzarlo. Ancora meglio sarebbe passare a HttpClient se si utilizza .NET 4.5 poiché è "nativamente" asincrono.

Utilizzando .NET 4 e C# 4, è ancora possibile utilizzare Task per avvolgerli e semplificare l'accesso al risultato finale. Ad esempio, un'opzione potrebbe essere la seguente. Nota che ha il blocco del metodo Main fino a quando la stringa di contenuto è disponibile, ma in uno scenario "reale" probabilmente passerai l'attività a qualcos'altro o stringa un altro ContinueWith al di fuori di esso o altro.

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

Grazie ancora per la risposta e il tempo. – gdp

+0

Una domanda veloce, quando si accede ai metodi MakeAsyncRequest() Proprietà dei risultati, come posso accertarmi che il risultato sia sempre terminato quando cerco di utilizzare la risposta. – gdp

+0

La proprietà Result bloccherà fino a quando non sarà completata. –

2

Una volta che si è asincroni, non si può mai tornare indietro. Da lì hai solo realmente accesso al callback di async. è possibile aumentare la complessità di questo e fare alcuni threading & waithandles ma che può essere piuttosto uno sforzo doloroso.

Tecnicamente, è anche possibile dormire il thread quando è necessario attendere i risultati, ma non è consigliabile, è possibile effettuare una normale richiesta http in quel punto.

In C# 5 hanno comandi asincroni/attendi che renderanno più semplice ottenere i risultati della chiamata asincrona nel thread principale.

+0

il threading è quello che ho avuto modo di capirci. Grazie per il tuo contributo. – gdp

5

"Ancora meglio sarebbe passare a HttpClient se si sta utilizzando .NET 4.5 visto che e 'nativo' async". - assolutamente giusta risposta di James Manning. Questa domanda è stata fatta circa 2 anni fa. Ora abbiamo .NET Framework 4.5, che fornisce potenti metodi asincroni. Utilizzare HttpClient. Si consideri il seguente codice:

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 
      } 
     } 
    } 

Per utilizzare HttpGetAsync(), fare un nuovo metodo che è "asincrono" troppo. metodo è richiesto asincrono, perché abbiamo bisogno di usare "aspettiamo" in GetWebPage():

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

Ora, se si desidera ottenere pagina web il codice sorgente HTML in modo asincrono, basta chiamare GetWebPage ("indirizzo web ... "). Anche la lettura del flusso è asincrona.

NOTA: per utilizzare HttpClient .NET è necessario il framework 4.5. Inoltre è necessario aggiungere il riferimento System.Net.Http nel progetto e aggiungere anche "using System.Net.Http" per un facile accesso.

Per ulteriori lettura di come funziona questo approccio, visitare il sito: http://msdn.microsoft.com/en-us/library/hh191443(v=vs.110).aspx

L'utilizzo di Async: Async in 4.5: Worth the Await

Problemi correlati