2016-07-30 65 views
1

Ich habe angefangen zu lernen TPL Dataflow. Ich bin bemüht, den Unterschied zwischen Task.ContinueWith und Datenfluss zu finden. Unten sind die zwei Beispielcodes, die das gleiche Ziel haben. Zuerst wird mit Task.ContinueWith und später mit Datenfluss getan.
Unten ist das Beispiel mit Task.ContinueWithtask.continuewith vs Datenfluss in C#

var tk1 = Task.Run(() => 
{ 
    Console.WriteLine("Entered 1st Task"); 
    Thread.Sleep(3000); 
    return 2; 
}); 

tk1.ContinueWith((t) => 
{ 
    Console.WriteLine("Entered 2nd Task"); 
    Thread.Sleep(2000); 
    Console.WriteLine(t.Result); 
}); 

tk1.Wait(); 

und unten ist die gleiche

mit Datenfluß getan
var df1 = new TransformBlock<int,int>(t => 
{ 
    Console.WriteLine("Entered 1st DF"); 
    Thread.Sleep(3000); 
    return 2; 
}); 

var df2 = new ActionBlock<int>(t => 
{ 

    Console.WriteLine("Entered 2nd Task"); 
    Thread.Sleep(2000); 
    Console.WriteLine(t); 
}); 

df1.LinkTo(df2); 

df1.Completion.ContinueWith(t => 
df2.Complete()); 

df1.Post(2); 

df2.Completion.Wait(); 

Task.ContinueWith sieht einfach aus, als die lange Syntax, die Datenfluß zur Verfügung stellt. Kann jemand bitte den Unterschied zwischen den beiden klären.

Antwort

0

Datenfluss ich verwendet, um ein Compleax procesing Pipleins zu erstellen, wo der Fluss verzweigen und zusammenführen und loopen kann. (Das Beispiel, das Sie hier zeigen, ist zu einfach)

Task.ContinueWith wird in einem einfacheren Code verwendet, wenn der Ablauf in einer Liste von Funktionen nacheinander erfolgt.

1

Mit Ihrem Code, gibt es tatsächlich keinen Unterschied.

Aber Sie tun es falsch für den Datenfluss - was nutzt ein Transformationsblock, der immer nur ein Ergebnis unabhängig von der Eingabe erzeugt?

Bessere einige Verarbeitung tun ...

var df1 = new TransformBlock<int,int>(input => 
    { 
     Console.WriteLine("Entered 1st DF"); 
     Thread.Sleep(3000); 
     return input+1; 
    }); 

... und dann sehen Sie den Unterschied:

Task.Run läuft nur einmal, sondern

df1.Post(2); 
df1.Post(5); 
df1.Post(27); 
df1.Post(-1); 

werden alle durchlaufen Ihr Datenfluss maschiert und produziert Ausgabe.

Und BTW: mit async/await anstelle von Task.ContinueWith kann Ihren Code viel einfacher und lesbarer machen.

0

Sie müssen sich für TPL Dataflow, die Grundlagen vollständig verstehen, wie jetzt Sie tun Dinge versuchen, die leicht von TPL Dataflow Pipeline selbst getan werden kann:

df1.LinkTo(df2, new DataflowLinkOptions { PropagateCompletion = true }); 

Sie brauchen jetzt nicht ContinueWith für eine verwenden, df1.Completion, aber Sie müssen noch die df1 Block (hässlich Namensgebung, übrigens) bis (Überraschung) complete, da sie nicht weiß, benachrichtigen, wenn, mit Aufgabe Vergleich zu beenden:

df1.Post(2); 
df1.Complete(); 

Beim Aufruf dieser Methode werden alle anderen Nachrichten verweigern df1 Block gesendet, und nachdem es Puffer leer wurde, wird die Fertigstellung unten in der Pipeline ausbreiten, so dass Sie einfach darauf warten müssen (entweder synchron oder asynchron):

df2.Completion.Wait(); 
// or 
await df2.Completion; 

Im Grunde ist der Unterschied, dass Task nur einmal ausgeführt werden kann, im Vergleich mit Block, der für immer ausgeführt wird, bis Sie es manuell abschließen.Beachten Sie, dass Sie die Task Completion für einen Block weiterhin fortsetzen können:

df2.Completion.ContinueWith(t => 
{ 
    // some other logic here 
});