2016-04-03 14 views
1

ich geschrieben habe, ein Verfahren unter Verwendung von Asynchron-Schlüsselwort zu verstehen, aber das Ergebnis kann es nicht verstehen, und der Grund ist es nicht wirklich funktioniert:Der Versuch, async/erwarten in C#

static async void ExampleWithValueReturned_Async(Stopwatch sw, SlowOperation opr1, SlowOperation opr2) 
{ 
    Console.WriteLine("Started processing ASYNC. Start: {0}", sw.Elapsed); 
    sw.Start(); 

    Console.WriteLine("2 Step0: {0}", sw.Elapsed); 
    var sum1_2 = await Task<double>.Factory.StartNew(() => opr1.PerformSlowOperation(1, true)); 
    Console.WriteLine("2 Step1: {0}", sw.Elapsed); 
    var sum2_2 = await Task<double>.Factory.StartNew(() => opr2.PerformSlowOperation(1, true)); 
    Console.WriteLine("2 Step2: {0}", sw.Elapsed); 

    Console.WriteLine("Operation 1 gave sum: {0}", sum1_2.ToString("0.##")); 
    Console.WriteLine("Operation 2 gave sum: {0}", sum2_2.ToString("0.##")); 
    Console.WriteLine("Stopped processing ASYNC. Stop: {0}", sw.Elapsed); 
    sw.Stop(); 

    sw.Reset(); 
    Console.WriteLine(""); 
} 

Ich hatte erwartet, dies zu Sie laufen doppelt so schnell wie die Inline-Verarbeitung, da PerformSlowOperation parallel läuft. Meine Erwartung war, dass die Produktion von sum1_2 und sum2_2 zur gleichen Zeit stattfindet, während die Analyse des Ergebnisses basierend auf den Stoppuhr-Logs zeigt, dass beide Werte genauso verarbeitet werden wie im Fall der Inline-Verarbeitung. Die Gesamtzeit ist in beiden Fällen gleich. Wieso ist es so?

+1

Nebenbei bemerkt, 'Task.Factory.StartNew' ist eine gefährliche API. Verwenden Sie stattdessen "Task.Run". –

+1

Versuchen Sie asynchrone Void-Konstruktionen zu vermeiden. Suchen Sie nach weiteren Informationen auf dieser Seite (https://msdn.microsoft.com/en-us/magazine/jj991977.aspx). –

+0

@JeroenHeier Prost für dein Feedback. Werfen Sie einen Blick – Bartosz

Antwort

4

Das C# await Schlüsselwort tut genau das, was das Wort sagt, es wartet auf die Ausführung der Funktion, bevor es zur nächsten Zeile weitergeht. Wenn Sie das Schlüsselwort await nicht verwendet haben, wird es im Hintergrund ausgeführt und die Ausführung des restlichen Codes wird fortgesetzt. Dies erlaubt Ihnen jedoch nichts mit den Ergebnissen zu tun.

Um beide Tasks parallel auszuführen, müssen Sie explizit angeben, dass auf der Tasks warten soll, bevor Sie fortfahren und nicht nur auf jeden Task warten.

Task t1 = Task<double>.Factory.StartNew(() => opr1.PerformSlowOperation(1, true)); 
Task t2 = Task<double>.Factory.StartNew(() => opr2.PerformSlowOperation(1, true)); 
await Task.WhenAll(t1,t2); 
var sum1_2 = t1.Result; 
var sum2_2 = t2.Result; 

Der obige Code wartet, bis beide beendet sind, und führt sie parallel durch, bevor der Rest des Codes fortgesetzt wird.

Der Grund, warum das Schlüsselwort existiert, ist nicht die Aktivierung paralleler Tasks. Es ermöglicht es Anwendungen, auf den Abschluss einer einzelnen asynchronen Methode zu warten, bevor der Rest des Codes ausgeführt wird. Es ist sehr nützlich in ASP.NET, wo eine lange laufende Aufgabe verschwenderisch Threads hält, mit await sagt ASP.NET, dass es die Steuerung des Threads auf eine andere Anfrage aufgeben kann, bis die lang laufende Anfrage der vorherigen Aufgabe dann beendet wird Es endet damit, dass es die Kontrolle über den Thread zurückgibt.

+2

Große Antwort, vielen Dank! – Bartosz

+0

Keine Sorge, froh, dass es geholfen hat! –