2013-08-13 14 views
6

Ho bisogno di rendere il seguente codice asincrono e attendibile.Come rendere ordinario WebRequest asincrono e attendibile?

Ho bisogno di ottenere molti dati dal server web, e quindi questi dati verranno utilizzati per popolare la pagina xaml nella mia applicazione.

Quindi, ho bisogno del metodo DefLogin() per essere attendibile.

È possibile?

public void DefLogin() 
    { 
     postData = "My Data To Post"; 
     var url = new Uri("Url To Post to", UriKind.Absolute); 
     webRequest = WebRequest.Create(url); 
     webRequest.Method = "POST"; 
     webRequest.ContentType = "text/xml"; 
     webRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallback), webRequest); 
    } 

    public void GetRequestStreamCallback(IAsyncResult asynchronousResult) 
    { 
     webRequest = (HttpWebRequest)asynchronousResult.AsyncState; 
     Stream postStream = webRequest.EndGetRequestStream(asynchronousResult); 
     byte[] byteArray = Encoding.UTF8.GetBytes(postData); 
     postStream.Write(byteArray, 0, byteArray.Length); 
     postStream.Close(); 
     Debug.WriteLine("Start BEGINGetResponse"); 
     webRequest.BeginGetResponse(new AsyncCallback(GetResponseCallback), webRequest); 
    } 

    public void GetResponseCallback(IAsyncResult asynchronousResult) 
    { 
     try 
     { 
      HttpWebRequest webRequest = (HttpWebRequest)asynchronousResult.AsyncState; 
      HttpWebResponse response; 
      response = (HttpWebResponse)webRequest.EndGetResponse(asynchronousResult); 
      Stream streamResponse = response.GetResponseStream(); 
      StreamReader streamReader = new StreamReader(streamResponse); 
      string Response = streamReader.ReadToEnd(); 
      streamResponse.Close(); 
      streamReader.Close(); 
      response.Close(); 
      if (Response == "") 
      { 
       //show some error msg to the user   
       Debug.WriteLine("ERROR"); 

      } 
      else 
      { 
       //Your response will be available in "Response" 
       Debug.WriteLine(Response); 
      } 
     } 
     catch (WebException) 
     { 
      //error  
     } 
    } 

Ho visto questa domanda su StackOverflow: Converting ordinary Http Post web request with Async and Await, ma non riuscivo a capire la risposta corretta.

Si prega di qualcuno può aiutare? Sarei davvero grato!

risposta

13

È possibile utilizzare TaskFactory.FromAsync per convert APM to TAP, facendo un sacco di piccoli metodi di estensione in questo modo:

public static Task<Stream> GetRequestStreamAsync(this WebRequest request) 
{ 
    return TaskFactory.FromAsync(request.BeginGetRequestStream, request.EndGetRequestStream, null); 
} 

e fare lo stesso per WebRequest.GetResponse e (se necessario) Stream.Write, Stream.Flush, ecc

Poi puoi scrivere la tua logica attuale usando async e await senza richiamate:

public async Task DefLoginAsync() 
{ 
    postData = "My Data To Post"; 
    var url = new Uri("Url To Post to", UriKind.Absolute); 
    webRequest = WebRequest.Create(url); 
    webRequest.Method = "POST"; 
    webRequest.ContentType = "text/xml"; 
    using (Stream postStream = await webRequest.GetRequestStreamAsync()) 
    { 
     byte[] byteArray = Encoding.UTF8.GetBytes(postData); 
     await postStream.WriteAsync(byteArray, 0, byteArray.Length); 
     await postStream.FlushAsync(); 
    } 
    try 
    { 
     string Response; 
     using (var response = (HttpWebResponse)await webRequest.GetResponseAsync()); 
     using (Stream streamResponse = response.GetResponseStream()) 
     using (StreamReader streamReader = new StreamReader(streamResponse)) 
     { 
      Response = await streamReader.ReadToEndAsync(); 
     } 
     if (Response == "") 
     { 
      //show some error msg to the user   
      Debug.WriteLine("ERROR"); 

     } 
     else 
     { 
      //Your response will be available in "Response" 
      Debug.WriteLine(Response); 
     } 
    } 
    catch (WebException) 
    { 
     //error  
    } 
} 
+2

Sorprendente risposta. Questo merita davvero più credito. Dalla mia esperienza, i metodi di estensione dovrebbe essere simile a "tornare Task .Factory.FromAsync (ecc ...)", altrimenti si incorrerà in "La chiamata è ambigua" errore. Inoltre, NON omettere gli use(): sono molto importanti per assicurarsi che il flusso sia chiuso prima di EndGet ___(). –

Problemi correlati