2010-11-13 2 views
5

Wie erstellt man eine echte Funktionspipeline mit C#? Ich habe wie eine Idee wie folgt, aber es ist keine echte PipelineWie wird eine echte Funktionspipeline in C# implementiert?

public static IEnumerable<T> ForEachPipeline<T>(this IEnumerable<T> source, params Func<T, T>[] pipeline) 
{ 
foreach (var element in source) { 
    yield return ExecutePipeline(element, pipeline); 
} 
} 

private static T ExecutePipeline<T>(T element, IEnumerable<Func<T, T>> jobs) 
{ 
var arg = element; 
T result = default(T); 
foreach (var job in jobs) { 
    result = job.Invoke(arg); 
    arg = result; 
} 
return result; 
} 

In dem obigen Code jedes Element IEnumerable<T> würde nur in der Lage in die Rohrleitung zu erhalten, nachdem das vorherige Element beendet alle Funktionen ausführt (dh Ausgänge die Pipeline), aber gemäß der Definition, wenn element1 die Ausführung von func1 beendet und die Ausführung von func2 beginnt, sollte element2 zu diesem Zeitpunkt mit der Ausführung von func1 und so weiter beginnen, damit der Datenfluss in der Pipeline fortgesetzt wird.

Ist diese Art von Szenario in C# zu implementieren? Wenn möglich, geben Sie mir bitte einen Beispielcode.

+0

Es gibt nur einen einzigen Ausführungskontext, es sei denn, es werden Threads eingeführt (der alternative Ansatz mit einem einzigen Thread ist nur das nicht-faule Ergebnis, das bei jedem Schritt entsteht). Bei Threads ist jede Stufe nur eine FIFO-Warteschlange, die Nachrichten um eine "Pumpe" herum leitet. Threads (eigentlich Parallelität) erhöhen ebenfalls die Komplexität erheblich, siehe vielleicht die .NET4 "Parallel" -Methoden. –

+0

Ich habe kein Problem bei der Einführung von Threads, ich brauche die Arbeit sowieso getan werden .. bitte teilen Sie einige Ideen –

+0

Würde PLINQ dies nicht schon lösen? http://msdn.microsoft.com/en-us/library/dd460688.aspx – bzlm

Antwort

0

Von Kommentar: Es gibt nur einen einzigen Ausführungskontext, es sei denn, Threads werden eingeführt (der alternative Ansatz mit einem einzigen Thread ist nur das nicht faule Ergebnis, das bei jedem Schritt entsteht). Bei Threads ist jede Stufe nur eine FIFO-Warteschlange, die Nachrichten um eine "Pumpe" herum leitet. Threads (eigentlich Parallelität) erhöhen ebenfalls die Komplexität erheblich, siehe vielleicht die .NET4 "Parallel" -Methoden.

Eine "einfache" Methode ist nur die Konfiguration von N "Starts" mit Parallel.ForEach - wenn und nur wenn Sie garantieren können, dass die Berechnungen frei von Nebenwirkungen sind.

Bearbeiten: Siehe Kommentar (e).

+0

Das war eine Idee, aber in diesem Muster, wie stelle ich sicher, dass das Ergebnis Enumerable in der gleichen Reihenfolge wie die Quelle Enumerable ist? –

+1

@AnindyaChatterjee: Anstatt "Parallel.ForEach" zu verwenden, verwenden Sie Parallel Linq (PLINQ) über die 'ParallelEnumerable'-Erweiterungsmethoden, zu denen auch das' AsOrdered' gehört (http://msdn.microsoft.com/en-us/library) /dd642142.aspx) Operator, um Ihre Eingabeordnung zu verwalten. – Richard

0

Dieses Verhalten ist effizienter als eine echte Pipeline. Pipelining ist nur dann sinnvoll, wenn Operationen parallel ausgeführt werden können. Alle diese Jobs teilen jedoch einen einzelnen CPU-Thread und müssen daher sequenziell ausgeführt werden, selbst wenn sie in Pipelines ausgeführt werden.

Wenn Sie verstehen, dass es keine Leistungsverbesserung geben wird und trotzdem weiterleiten möchten, hinterlassen Sie einen Kommentar und ich werde zeigen, wie, aber zuerst möchte ich sicherstellen, dass Sie wissen, wonach Sie fragen.

+0

Warum glauben Sie, dass eine echte Pipeline den Durchsatz nicht erhöht? Jedenfalls bin ich sehr daran interessiert, eine echte Pipeline-Implementierung zu sehen, und ich prüfe den Durchsatz der beiden. –

0

Ich glaube, ein Haupt architektonisches Element fehlt, ob der Job bearbeitet wird oder nicht. Pipeline ist sehr ähnlich wie die traditionelle GoF Verantwortungskette, werfen Sie einen Blick hier, wenn Sie das GoF Buch nicht herum haben:

http://www.dofactory.com/Patterns/PatternChain.aspx#_self1

Ich glaube, Sie haben Ihre „T“ bis zu einem gewissen Schnittstelle zu beschränken, teilt die Pipeline mit, wenn der Job bearbeitet wurde (verwenden Sie die Anweisung "where").

Schauen Sie auch in das PLINQ-Framework. Ich weiß, dass es nicht genau das ist, wonach Sie suchen (dort besteht die Absicht, mehrere Jobs parallel auszuführen), aber es könnte Ihnen einige gute Ideen geben.

+0

Wenn ich dieses Muster anwende, ist es dasselbe wie der oben erwähnte Code, es wird sowieso keine echte Pipeline sein. –

Verwandte Themen