Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In PLINQ besteht das Ziel darin, die Leistung zu maximieren und gleichzeitig die Korrektheit aufrechtzuerhalten. Eine Abfrage sollte so schnell wie möglich ausgeführt werden, aber dennoch die richtigen Ergebnisse erzielen. In einigen Fällen muss die Reihenfolge der Quellsequenz beibehalten werden; Die Sortierung kann jedoch rechenintensiv sein. Daher behält PLINQ standardmäßig nicht die Reihenfolge der Quellsequenz bei. In diesem Zusammenhang ähnelt PLINQ LINQ to SQL, steht jedoch im Gegensatz zu LINQ to Objects, das die Sortierung bewahrt.
Um das Standardverhalten außer Kraft zu setzen, können Sie die Reihenfolge beibehalten, indem Sie den AsOrdered Operator für die Quellsequenz verwenden. Sie können die Reihenfolgenerhaltung später in der Abfrage mithilfe der AsUnordered Methode deaktivieren. Bei beiden Methoden wird die Abfrage basierend auf den Heuristiken verarbeitet, die bestimmen, ob die Abfrage parallel oder sequenziell ausgeführt werden soll. Weitere Informationen finden Sie unter Understanding Speedup in PLINQ.
Das folgende Beispiel zeigt eine ungeordnete parallele Abfrage, die nach allen Elementen filtert, die einer Bedingung entsprechen, ohne die Ergebnisse auf irgendeine Weise zu ordnen.
var cityQuery =
(from city in cities.AsParallel()
where city.Population > 10000
select city).Take(1000);
Dim cityQuery = From city In cities.AsParallel()
Where city.Population > 10000
Take (1000)
Diese Abfrage erzeugt nicht unbedingt die ersten 1000 Städte in der Quellsequenz, die die Bedingung erfüllen, sondern einige von 1000 Städten, die die Bedingung erfüllen. PLINQ-Abfrageoperatoren partitionieren die Quellsequenz in mehrere Untersequencen, die als gleichzeitige Aufgaben verarbeitet werden. Wenn die Erhaltung der Reihenfolge nicht angegeben ist, werden die Ergebnisse jeder Partition an die nächste Phase der Abfrage in einer beliebigen Reihenfolge übergeben. Außerdem kann eine Partition eine Teilmenge ihrer Ergebnisse liefern, bevor sie die verbleibenden Elemente weiter verarbeitet. Die resultierende Reihenfolge kann jedes Mal unterschiedlich sein. Die Anwendung kann dies nicht steuern, da sie davon abhängt, wie das Betriebssystem die Threads plant.
Im folgenden Beispiel wird das Standardverhalten überschrieben, indem der AsOrdered Operator in der Quellsequenz verwendet wird. Dadurch wird sichergestellt, dass die Take Methode die ersten 1000 Städte in der Quellsequenz zurückgibt, die die Bedingung erfüllen.
var orderedCities =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
Dim orderedCities = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Take (1000)
Diese Abfrage wird jedoch wahrscheinlich nicht so schnell ausgeführt wie die ungeordnete Version, da sie die ursprüngliche Sortierung während der gesamten Partitionen nachverfolgen muss und zur Zusammenführungszeit sicherstellen muss, dass die Sortierung konsistent ist. Daher empfiehlt es sich, nur dann zu verwenden AsOrdered , wenn sie erforderlich ist, und nur für die Teile der Abfrage, für die sie erforderlich ist. Wenn die Beibehaltung der Reihenfolge nicht mehr notwendig ist, deaktivieren Sie diese mit AsUnordered. Im folgenden Beispiel wird dies erreicht, indem zwei Abfragen verfasst werden.
var orderedCities2 =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
var finalResult =
from city in orderedCities2.AsUnordered()
join p in people.AsParallel()
on city.Name equals p.CityName into details
from c in details
select new
{
city.Name,
Pop = city.Population,
c.Mayor
};
foreach (var city in finalResult) { /*...*/ }
Dim orderedCities2 = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Select city
Take (1000)
Dim finalResult = From city In orderedCities2.AsUnordered()
Join p In people.AsParallel() On city.Name Equals p.CityName
Select New With {.Name = city.Name, .Pop = city.Population, .Mayor = city.Mayor}
For Each city In finalResult
Console.WriteLine(city.Name & ":" & city.Pop & ":" & city.Mayor)
Next
Beachten Sie, dass PLINQ die Reihenfolge einer Sequenz beibehält, die von Reihenfolge erzwingenden Operatoren für den verbleibenden Teil der Abfrage erzeugt wird. Mit anderen Worten, Operatoren wie OrderBy und ThenBy werden behandelt, als ob ihnen ein Aufruf von AsOrdered folgen würde.
Abfrageoperatoren und Sortierung
Mit den folgenden Abfrageoperatoren wird die Reihenfolgeerhaltung in alle nachfolgenden Abfragevorgänge eingeführt, oder bis AsUnordered aufgerufen wird.
Die folgenden PLINQ-Abfrageoperatoren können in einigen Fällen geordnete Quellsequenzen erfordern, um korrekte Ergebnisse zu erzielen:
Einige PLINQ-Abfrageoperatoren verhalten sich je nachdem, ob ihre Quellsequenz sortiert oder ungeordnet ist. In der folgenden Tabelle sind diese Operatoren aufgeführt.
Bediener | Ergebnis, wenn die Quellsequenz sortiert wird | Ergebnis, wenn die Quellsequenz nicht angeordnet ist |
---|---|---|
Aggregate | Nicht deterministische Ausgabe für nicht assoziative oder nichtkommutative Vorgänge | Nicht deterministische Ausgabe für nicht assoziative oder nichtkommutative Vorgänge |
All | Nicht anwendbar | Nicht anwendbar |
Any | Nicht anwendbar | Nicht anwendbar |
AsEnumerable | Nicht anwendbar | Nicht anwendbar |
Average | Nicht deterministische Ausgabe für nicht assoziative oder nichtkommutative Vorgänge | Nicht deterministische Ausgabe für nicht assoziative oder nichtkommutative Vorgänge |
Cast | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Concat | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Count | Nicht anwendbar | Nicht anwendbar |
DefaultIfEmpty | Nicht anwendbar | Nicht anwendbar |
Distinct | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
ElementAt | Angegebenes Element zurückgeben | Willkürliches Element |
ElementAtOrDefault | Angegebenes Element zurückgeben | Willkürliches Element |
Except | Ungeordnete Ergebnisse | Ungeordnete Ergebnisse |
First | Angegebenes Element zurückgeben | Willkürliches Element |
FirstOrDefault | Angegebenes Element zurückgeben | Willkürliches Element |
ForAll | Nicht deterministische, parallele Ausführung | Nicht deterministische, parallele Ausführung |
GroupBy | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
GroupJoin | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Intersect | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Join | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Last | Angegebenes Element zurückgeben | Willkürliches Element |
LastOrDefault | Angegebenes Element zurückgeben | Willkürliches Element |
LongCount | Nicht anwendbar | Nicht anwendbar |
Min | Nicht anwendbar | Nicht anwendbar |
OrderBy | Neu anordnen der Sequenz | Start eines neuen geordneten Abschnitts |
OrderByDescending | Neu anordnen der Sequenz | Start eines neuen geordneten Abschnitts |
Range | Nicht anwendbar (gleiche Standardeinstellung wie AsParallel ) | Nicht anwendbar |
Repeat | Nicht anwendbar (gleiche Standardeinstellung wie AsParallel) | Nicht anwendbar |
Reverse | Umkehrungen | Tut nichts |
Select | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Select (indiziert) | Sortierte Ergebnisse | Ungeordnete Ergebnisse. |
SelectMany | Sortierte Ergebnisse. | Ungeordnete Ergebnisse |
SelectMany (indiziert) | Sortierte Ergebnisse. | Ungeordnete Ergebnisse. |
SequenceEqual | Sortierter Vergleich | Ungeordneter Vergleich |
Single | Nicht anwendbar | Nicht anwendbar |
SingleOrDefault | Nicht anwendbar | Nicht anwendbar |
Skip | Überspringt die ersten n-Elemente . | Überspringt alle n-Elemente . |
SkipWhile | Sortierte Ergebnisse. | Nicht deterministisch. Führt SkipWhile in der aktuellen beliebigen Reihenfolge aus. |
Sum | Nicht deterministische Ausgabe für nicht assoziative oder nichtkommutative Vorgänge | Nicht deterministische Ausgabe für nicht assoziative oder nichtkommutative Vorgänge |
Take | Verwendung der ersten n Elemente |
Verwendung aller n Elemente |
TakeWhile | Sortierte Ergebnisse | Nicht deterministisch. Ausführung von TakeWhile für die aktuelle willkürliche Reihenfolge |
ThenBy | Ergänzung zu OrderBy |
Ergänzung zu OrderBy |
ThenByDescending | Ergänzung zu OrderBy |
Ergänzung zu OrderBy |
ToArray | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
ToDictionary | Nicht anwendbar | Nicht anwendbar |
ToList | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
ToLookup | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Union | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Where | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Where (indiziert) | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Zip | Sortierte Ergebnisse | Ungeordnete Ergebnisse |
Ungeordnete Ergebnisse werden nicht aktiv neu angeordnet; sie haben einfach keine spezielle Sortierlogik angewendet. In einigen Fällen kann eine ungeordnete Abfrage die Reihenfolge der Quellsequenz beibehalten. Für Abfragen mit dem indizierten Select-Operator stellt PLINQ sicher, dass Elemente in aufsteigender Indexreihenfolge ausgegeben werden, jedoch wird nicht festgelegt, welcher Index welchem Element zugewiesen wird.