2010-11-16 6 views
14

Tenir compte de l'extrait de code suivant:Comment créer une méthode asynchrone en C# 4 selon les meilleures pratiques?

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

Il devrait revenir Task<string>, envoyer la demande HTTP POST avec des données, le retour d'un résultat de serveur web sous une forme de ficelle et être le plus efficace possible. Avez-vous détecté des problèmes concernant le flux asynchrone dans l'exemple ci-dessus?

  • Avez-vous détecté des problèmes concernant le flux asynchrone dans l'exemple ci-dessus?
  • Est-il correct d'avoir .Wait() dans .ContinueWith() dans cet exemple
  • Voyez-vous d'autres problèmes avec cette paix de code (en mettant de côté la gestion des exceptions pour le moment)?
+17

Vous devez accepter certaines réponses de vos autres questions – Jimmy

+0

Vous pouvez envisager de renommer votre objet Tâche car il existe déjà un objet Tâche dans .NET 4. Bien que vous puissiez les faire fonctionner ensemble, il peut être plus facile de simplement changer votre nomenclature. –

+0

Mystere Man, je n'ai aucune déclaration de tâche personnalisée. Le type de tâche que j'utilise provient de .NET 4.0 BCL. –

Répondre

3

Si le code C async lié # 4.0 est énorme et laid - il y a une chance qu'il est mis en œuvre correctement. Si c'est court et agréable, alors ce n'est probablement pas le cas;)

.. bien, vous pouvez le rendre plus attrayant en créant des méthodes d'extension sur WebRequest, classes de flux et nettoyer la méthode principale.

P.S.: J'espère que C# 5.0 avec son nouveau mot-clé async et library sera publié bientôt.

Référence: http://msdn.microsoft.com/en-us/vstudio/async.aspx

+0

Nouvelles fonctionnalités dans C# 5.0 à PDC2010: http://player.microsoftpdc.com/Session/1b127a7d-300e-4385-af8e-ac747fee677a –

+0

+1 pour énorme et moche = correct –

+5

Vous avez peut-être raison sur "énorme et moche" , mais je ne vois pas comment cela répond aux questions concrètes de Grief. Je suis surpris que ce soit accepté. –

0

Vous avez raison de penser que les temps d'attente ne sont pas nécessaires - Résultat bloquera jusqu'à ce qu'un résultat est prêt.


Cependant, d'une manière encore plus facile serait de se baser hors utiliser les exemples fournis dans le ParallelExtensionsExtras library.

Ils ont fait des extensions pour WebClient qui font exactement ce que vous cherchez:

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

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

Vous pouvez en lire davantage dans this post on the Parallel Programming with .NET blog.

+0

Merci pour la contribution. Pourquoi pensez-vous que le type 'HttpWebRequest' est marqué comme obsolète? –

+2

'HttpWebRequest' n'est pas marqué obsolète, et en fait' WebClient' l'utilise. Peut-être que vous pensez au [constructeur] (http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.httpwebrequest.aspx). Ce * est * obsolète, car vous êtes censé utiliser 'WebRequest.Create' à la place. –

+0

Oups! Je vais résoudre ça. – porges

Questions connexes