Zusammenführungsoptionen in PLINQ

Wenn eine Abfrage parallel ausgeführt wird, partitioniert PLINQ die Quellsequenz, damit mehrere Threads verschiedene Teile gleichzeitig, zumeist in separaten Threads bearbeiten können. Wenn die Ergebnisse in einem Thread genutzt werden sollen, z. B. in einer foreach-Schleife (For Each in Visual Basic), müssen die Ergebnisse von jedem Thread wieder in einer Sequenz zusammengeführt werden. Die Art der von PLINQ ausgeführten Zusammenführung hängt von den Operatoren in der Abfrage ab. Bei Operatoren, die eine neue Reihenfolge der Ergebnissen erzeugen, müssen beispielsweise alle Elemente aus allen Threads gepuffert werden. Aus Sicht des Consumerthreads (der Thread des Anwendungsbenutzers) kann die Ausführung einer vollständig gepufferten Abfrage relativ lange dauern, bevor erste Ergebnisse erzielt werden. Andere Operatoren werden standardmäßig teilweise gepuffert, d. h. sie geben Ergebnisse in Batches aus. Ein Operator, ForAll<TSource>, wird standardmäßig nicht gepuffert. Er gibt alle Elemente aus allen Thread unmittelbar aus.

Mit der WithMergeOptions<TSource>-Methode können Sie einen Hinweis in PLINQ angeben, der die durchzuführende Art der Zusammenführung kennzeichnet, wie im folgenden Beispiel gezeigt.

        Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                        Where n Mod 2 = 0
                        Select ExpensiveFunc(n)

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);

Das vollständige Beispiel finden Sie unter Gewusst wie: Angeben von Zusammenführungsoptionen in PLINQ.

Wenn die konkrete Abfrage die angeforderte Option nicht unterstützt, wird die Option ignoriert. In den meisten Fällen müssen Sie keine Zusammenführungsoption für eine PLINQ-Abfrage angeben. In einigen Fällen finden Sie mittels Tests und Messung jedoch ggf. heraus, dass eine Abfrage am besten in einem nicht standardmäßigen Modus ausgeführt wird. Diese Option wird häufig verwendet, wenn die Ergebnisse eines blockzusammenführenden Operators per Streaming übertragen werden sollen, um eine Benutzeroberfläche mit kürzeren Reaktionszeiten bereitzustellen.

ParallelMergeOptions

Die ParallelMergeOptions-Enumeration schließt die folgenden Optionen ein, die für unterstützte Abfrageformen angeben, wie die abschließende Ausgabe der Abfrage ausgegeben wird, wenn die Ergebnisse in einem Thread genutzt werden:

  • Not Buffered

    Die NotBuffered-Option bewirkt, dass jedes verarbeitete Element von jedem Thread zurückgegeben wird, sobald es erzeugt wurde. Dieses Verhalten entspricht somit einem "Streaming" der Ausgabe. Wenn der AsOrdered()-Operator in der Abfrage vorhanden ist, behält NotBuffered die Reihenfolge der Quellelemente bei. Obwohl NotBuffered Ergebnisse ausgibt, sobald diese verfügbar sind, kann die insgesamt zum Erzeugen der Ergebnisse benötigte Zeit länger sein als mit einer der anderen Zusammenführungsoptionen.

  • Auto Buffered

    Die AutoBuffered-Option bewirkt, dass die Abfrage Elemente in einem Puffer sammelt und den Pufferinhalt in regelmäßigen Abständen vollständig an den Comsumerthread ausgibt. Dies entspricht einer Ausgabe der Quelldaten in "Blöcken" anstelle des bei NotBuffered verwendeten "Streamings". AutoBuffered benötigt zum Bereitstellen des ersten Elements im Consumerthread möglicherweise länger als NotBuffered. Die Größe des Puffers und das genaue Ausgabeverhalten können nicht konfiguriert werden und variieren abhängig von verschiedenen, die Abfrage betreffenden Faktoren.

  • FullyBuffered

    Die FullyBuffered-Option bewirkt, dass die Ausgabe der gesamten Abfrage gepuffert wird, bevor eines der Elemente ausgegeben wird. Wenn Sie diese Option verwenden, dauert es ggf. länger, bis das erste Element im Consumerthread bereitgestellt wird, das Gesamtergebnis wird allerdings meist schneller erzeugt als bei den anderen Optionen.

Abfrageoperatoren mit Unterstützung von Zusammenführungsoptionen

In der folgenden Tabelle sind die Operatoren, die, abhängig von den angegebenen Beschränkungen, alle Zusammenführungsoptionsmodi unterstützen.

Operator

Beschränkungen

AsEnumerable<TSource>

Keine

Cast<TResult>

Keine

Concat

Nicht geordnete Abfragen, die nur über eine Array- oder Listenquelle verfügen

DefaultIfEmpty

Keine

OfType<TResult>

Keine

Reverse<TSource>

Nicht geordnete Abfragen, die nur über eine Array- oder Listenquelle verfügen

Select

Keine

SelectMany

Keine

Skip<TSource>

Keine

Take<TSource>

Keine

Where

Keine

Alle anderen PLINQ-Abfrageoperatoren ignorieren ggf. vom Benutzer bereitgestellte Zusammenführungsoptionen. Einige Abfrageoperatoren, z. B. Reverse<TSource> und OrderBy, können Elemente erst ausgeben, wenn alle Elemente erzeugt und neu sortiert wurden. Wenn ParallelMergeOptions in einer Abfrage verwendet wird, die zudem einen Operator wie Reverse<TSource> enthält, wird das Zusammenführungsverhalten in der Abfrage erst angewendet, nachdem dieser Operator Ergebnisse erzeugt hat.

Die Fähigkeit einiger Operatoren, Zusammenführungsoptionen zu verarbeiten, hängt vom Typ der Quellsequenz und von der vorherigen Verwendung des AsOrdered-Operators in der Abfrage ab. ForAll<TSource> lautet immer NotBuffered, d. h., die Elemente werden unmittelbar ausgegeben. OrderBy lautet immer FullyBuffered, d. h., die Elemente werden erst ausgegeben, nachdem die gesamte Liste sortiert wurde.

Siehe auch

Aufgaben

Gewusst wie: Angeben von Zusammenführungsoptionen in PLINQ

Konzepte

Paralleles LINQ (PLINQ)