2010-11-16 12 views
14

Considere el siguiente fragmento de código:¿Cómo crear un método asíncrono en C# 4 de acuerdo con las mejores prácticas?

public static Task<string> FetchAsync() 
{ 
    string url = "http://www.example.com", message = "Hello World!"; 

    var request = (HttpWebRequest)WebRequest.Create(url); 
    request.Method = WebRequestMethods.Http.Post; 

    return Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null) 
     .ContinueWith(t => 
     { 
      var stream = t.Result; 
      var data = Encoding.ASCII.GetBytes(message); 
      Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, data, 0, data.Length, null, TaskCreationOptions.AttachedToParent) 
       .ContinueWith(t2 => { stream.Close(); }); 
     }) 
     .ContinueWith<string>(t => 
     { 
      var t1 = 
       Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null) 
       .ContinueWith<string>(t2 => 
       { 
        var response = (HttpWebResponse)t2.Result; 
        var stream = response.GetResponseStream(); 
        var buffer = new byte[response.ContentLength > 0 ? response.ContentLength : 0x100000]; 
        var t3 = Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null, TaskCreationOptions.AttachedToParent) 
         .ContinueWith<string>(t4 => 
         { 
          stream.Close(); 
          response.Close(); 
          if (t4.Result < buffer.Length) 
          { 
           Array.Resize(ref buffer, t4.Result); 
          } 
          return Encoding.ASCII.GetString(buffer); 
         }); 
        t3.Wait(); 
        return t3.Result; 
       }); 
      t1.Wait(); 
      return t1.Result; 
     }); 
} 

debe devolver Task<string>, enviar solicitud HTTP POST con algunos datos, devuelve un resultado de servidor web en una forma de cadena y ser lo más eficiente posible.

  • ¿Ha detectado algún problema relacionado con el flujo asíncrono en el ejemplo anterior?
  • ¿Está bien tener .Wait() dentro .ContinuarCon() en este ejemplo
  • ¿Ve algún otro problema con esta paz de código (dejando de lado el manejo de excepciones por ahora)?
+17

Debe aceptar algunas respuestas de sus otras preguntas – Jimmy

+0

Es posible que desee considerar cambiar el nombre de su objeto Task ya que hay un objeto Task en .NET 4. Si bien puede hacer que funcionen juntos, puede ser más fácil simplemente cambiar su nomenclatura. –

+0

Mystere Man, no tengo ninguna declaración personalizada de tareas. El tipo de tarea que estoy usando proviene de .NET 4.0 BCL. –

Respuesta

3

Si asíncrono relacionadas con el código C# 4.0 es enorme y fea - existe la posibilidad de que se aplique correctamente. Si es bueno y corto, lo más probable es que no lo sea;)

.. aunque, puede hacer que se vea más atractivo creando métodos de extensión en WebRequest, Clases de flujo y limpie el método principal.

P.S.: Espero que C# 5.0 con su nueva palabra clave async y library salga pronto.

Referencia: http://msdn.microsoft.com/en-us/vstudio/async.aspx

+0

Nuevas características en C# 5.0 en PDC2010: http://player.microsoftpdc.com/Session/1b127a7d-300e-4385-af8e-ac747fee677a –

+0

+1 para enorme y feo = correcto –

+5

Puede tener razón acerca de "enorme y feo" , pero no veo cómo responde esto a ninguna de las preguntas concretas de Grief. Me sorprende que haya sido aceptado. –

0

estás en lo correcto al pensar que las esperas son innecesarios - El resultado se bloqueará hasta resultado está listo.


Sin embargo, una manera más fácil sería basar fuera utilizar los ejemplos proporcionados en el ParallelExtensionsExtras library.

Ellos han hecho extensiones de WebClient que hacen exactamente lo que estás buscando:

static Task<string> FetchAsync() 
{ 
    string url = "http://www.example.com", message = "Hello World!"; 

    return new WebClient().UploadStringTask(url, "POST", message); 
} 

Usted puede leer más sobre esto en this post on the Parallel Programming with .NET blog.

+0

Gracias por la entrada. ¿Por qué crees que el tipo 'HttpWebRequest' está marcado como obsoleto? –

+2

'HttpWebRequest' no está marcado como obsoleto, y de hecho' WebClient' lo usa. Tal vez estás pensando en el [constructor] (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.httpwebrequest.aspx). Ese * es * obsoleto, porque se supone que debes usar 'WebRequest.Create' en su lugar. –

+0

¡Uy! Arreglará eso. – porges

Cuestiones relacionadas