2016-09-28 5 views
0

zu schreiben, könnte es eine dumme Frage sein. Ich überschreibe eine synchrone HTTP-Sendedatenfunktion zu asynchron mit TAP. Die Funktion sieht wie folgt aus:Korrekter Weg, um Sync-Funktion mit TAP

public void SendToUrl(string url, string content) 
{ 
    try 
    { 
     byte[] payload = Encoding.ASCII.GetBytes(content); 
     Stopwatch sw = Stopwatch.StartNew(); 
     HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 
     request.Method = "POST"; 
     request.ContentType = "text/plain"; 
     request.ContentLength = payload.Length; 

     using (Stream stream = request.GetRequestStream()) 
     { 
      stream.Write(payload, 0, payload.Length); 
     } 

     using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 
     { 
      sw.Stop(); 
      if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Accepted) 
      { 
       .... 
      } 
      else 
      { 
       .... 
      } 
     } 
    } 
    catch // error handling omitted 
    { 
    } 
} 

Zunächst Ich denke, es ist sehr einfach, ersetzen Sie einfach alle Sync-Funktionen NET-Bibliothek mit ihren awaitable XXXAsync Kollegen und Änderungsfunktion Signatur public async void SendToUrlAsync(...) (weil ich warten im Inneren nutzen die Funktion), aber nach dem Lesen einiger Artikel, es sieht aus wie viele Leute sagen async void ist nicht sicher (konnte den gesamten Prozess abstürzen), und es ist nur für Event-Handler konzipiert. Synchronous Void-Funktion sollte in async Task übersetzt werden, auch ich möchte hier eine Feuer-und-vergessen-Funktion. Wenn das wahr ist, um eine Aufgabe gewaltsam zurückzugeben, muss ich den ganzen Code innerhalb einer Task.Run(() => {...}) kapseln, die für mich redundant und seltsam aussieht, da ich mich wirklich nicht für das Rückgabe-Task-Objekt interessiere, aber wenn ich nicht darauf warte Compiler wird sich beschweren. Also, in meinem Fall, was ist der empfohlene Weg, um es neu zu schreiben? Vielen Dank.

Antwort

2

ersetzen alle Sync-NET-Bibliothek Funktionen mit ihren awaitable XXXAsync Kollegen und Änderungsfunktion Unterschrift

Eigentlich, wenn Sie leicht die Schritte hier ändern, ist es ein bisschen einfacher:

  1. ersetzen alle Sync-APIs mit ihren *Async Äquivalenten.
  2. await sie.

Der Compiler wird die Ihnen ein Fehler was darauf hindeutet, die richtige Signatur für Sie (in diesem Fall async Task).

gewaltsam zu einer Aufgabe zurückkehren, ich brauche gesamten Code zu kapseln innerhalb eines Task.Run

Nicht alle auf. Das Schlüsselwort async erstellt ein Task für Sie.

Nebenbei bemerkt ist der Write Aufruf unsicher - es ist für Streams (insbesondere Netzwerkstreams) möglich, nur einen Teilpuffer zu schreiben.

+0

Danke Stephen! Ihr Buch und Ihr Blog sind sehr hilfreich. Ich folgte Ihren Vorschlägen und fand, dass Sie Recht haben, mit Async-Schlüsselwort in der Signatur muss ich Task.Run nicht explizit aufrufen, um eine Aufgabe zu erstellen und zurückzugeben, glücklich, das zu lernen. Ich habe 2 Fragen: (1) Jetzt beschwert sich Compiler, dass ich meine neue Funktion SendToUrlAsync erwarten sollte, wenn ich Feuer-und-Vergessen-Verhalten haben möchte, was soll ich tun? (2) Können Sie etwas mehr über Stream.Write/Stream.WriteAsync erklären? Ich habe viele Beispiele gesehen, die Request-Streams auf diese Weise verwenden. Wenn dies nicht der Fall ist, was ist der richtige Weg, um Daten zu posten? Tks! – codewarrior

+0

Ich habe versucht, hinzuzufügen, wenn Anrufer SendToUrlAsync, jetzt Compiler sagte, ich musste den Anrufer zu asynchronen Task ändern. Ich kann sehen, dass ich bald jede Funktion in dieser Aufrufkette zu async Task ändern muss, ist das ein guter Weg? – codewarrior

+0

@codewarrior: Idealerweise ja, du solltest 'async' wachsen lassen. 1) Um Feuer-und-Vergessen zu machen (was [fast immer falsch] ist (http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html)), tun Sie ' var _ = SendToUrlAsync(); '. 2) Verwende 'BinaryWriter' oder lege es in einen' MemoryStream' und rufe 'CopyToAsync' auf. –

Verwandte Themen