Einführung in PLINQIntroduction to PLINQ

Parallel LINQ (PLINQ) ist eine parallele Implementierung des LINQ-Musters (Language-Integrated Query).Parallel LINQ (PLINQ) is a parallel implementation of the Language-Integrated Query (LINQ) pattern. PLINQ implementiert den kompletten Satz von LINQ-Standardabfrageoperatoren als Erweiterungsmethoden für den System.Linq-Namespace und verfügt über zusätzliche Operatoren für parallele Vorgänge.PLINQ implements the full set of LINQ standard query operators as extension methods for the System.Linq namespace and has additional operators for parallel operations. PLINQ kombiniert die Einfachheit und Lesbarkeit der LINQ-Syntax mit der Leistungsfähigkeit der parallelen Programmierung.PLINQ combines the simplicity and readability of LINQ syntax with the power of parallel programming.

Tipp

LINQ bietet ein einheitliches Modell für die typsichere Abfrage beliebiger aufzählbarer Datenquellen.If you're not familiar with LINQ, it features a unified model for querying any enumerable data source in a type-safe manner. LINQ to Objects ist der Name für LINQ-Abfragen von Auflistungen im Arbeitsspeicher, z. B. List<T>, und Arrays.LINQ to Objects is the name for LINQ queries that are run against in-memory collections such as List<T> and arrays. Dieser Artikel setzt Grundkenntnisse in LINQ voraus.This article assumes that you have a basic understanding of LINQ. Weitere Informationen finden Sie unter Language-Integrated Query (LINQ).For more information, see Language-Integrated Query (LINQ).

Was ist eine parallele Abfrage?What is a Parallel query?

Eine PLINQ-Abfrage entspricht weitgehend einer nicht parallelen LINQ to Objects-Abfrage.A PLINQ query in many ways resembles a non-parallel LINQ to Objects query. PLINQ-Abfragen werden, ebenso wie sequenzielle LINQ-Abfragen, auf alle IEnumerable- oder IEnumerable<T>-Datenquellen im Arbeitsspeicher angewendet und weisen eine verzögerte Ausführung auf, d. h. sie werden erst ausgeführt, wenn die Abfrage aufgelistet wird.PLINQ queries, just like sequential LINQ queries, operate on any in-memory IEnumerable or IEnumerable<T> data source, and have deferred execution, which means they do not begin executing until the query is enumerated. Der Hauptunterschied besteht darin, dass PLINQ versucht, alle Prozessoren im System vollständig auszuschöpfen.The primary difference is that PLINQ attempts to make full use of all the processors on the system. PLINQ partitioniert hierzu die Datenquelle in Segmente und führt dann die Abfrage für jedes Segment parallel in separaten Arbeitsthreads und auf mehreren Prozessoren aus.It does this by partitioning the data source into segments, and then executing the query on each segment on separate worker threads in parallel on multiple processors. In vielen Fällen bedeutet eine parallele Ausführung, dass die Abfrage deutlich schneller ausgeführt wird.In many cases, parallel execution means that the query runs significantly faster.

Durch die parallele Ausführung kann PLINQ für bestimmte Abfragen eine erheblich höhere Leistung als Legacycode erzielen. Häufig muss hierzu lediglich der AsParallel-Abfragevorgang zur Datenquelle hinzugefügt werden.Through parallel execution, PLINQ can achieve significant performance improvements over legacy code for certain kinds of queries, often just by adding the AsParallel query operation to the data source. Die Parallelität kann jedoch eigene Komplexitäten mit sich bringen, und nicht alle Abfragevorgänge werden in PLINQ schneller ausgeführt.However, parallelism can introduce its own complexities, and not all query operations run faster in PLINQ. Im Gegenteil, manche Abfragen werden durch die Parallelisierung sogar verlangsamt.In fact, parallelization actually slows down certain queries. Sie sollten daher wissen, wie sich bestimmte Aspekte, z. B. Sortierung, auf parallele Abfragen auswirken.Therefore, you should understand how issues such as ordering affect parallel queries. Weitere Informationen finden Sie unter Understanding Speedup in PLINQ (Grundlagen zur Beschleunigung in PLINQ).For more information, see Understanding Speedup in PLINQ.

Hinweis

In dieser Dokumentation werden Delegaten in PLINQ mithilfe von Lambdaausdrücken definiert.This documentation uses lambda expressions to define delegates in PLINQ. Falls Sie mit der Verwendung von Lambda-Ausdrücken in C# oder Visual Basic nicht vertraut sind, finden Sie entsprechende Informationen unter Lambda Expressions in PLINQ and TPL (Lambda-Ausdrücke in PLINQ und TPL).If you are not familiar with lambda expressions in C# or Visual Basic, see Lambda Expressions in PLINQ and TPL.

Der Rest dieses Artikels bietet eine Übersicht über die wichtigsten PLINQ-Klassen und erläutert, wie PLINQ-Abfragen erstellt werden.The remainder of this article gives an overview of the main PLINQ classes and discusses how to create PLINQ queries. Jeder Abschnitt enthält Links zu ausführlicheren Informationen und Codebeispielen.Each section contains links to more detailed information and code examples.

Die ParallelEnumerable-KlasseThe ParallelEnumerable Class

Die System.Linq.ParallelEnumerable-Klasse stellt nahezu die gesamte Funktionalität von PLINQ zur Verfügung.The System.Linq.ParallelEnumerable class exposes almost all of PLINQ's functionality. Diese Klasse sowie die restlichen Typen des System.Linq-Namespace werden in der Assembly "System.Core.dll" kompiliert.It and the rest of the System.Linq namespace types are compiled into the System.Core.dll assembly. Die standardmäßigen C#- und Visual Basic-Projekte in Visual Studio verweisen auf die Assembly und importiert den Namespace.The default C# and Visual Basic projects in Visual Studio both reference the assembly and import the namespace.

ParallelEnumerable enthält Implementierungen aller Standardabfrageoperatoren, die von LINQ to Objects unterstützt werden, auch wenn nicht für jeden eine Parallelisierung angestrebt wird.ParallelEnumerable includes implementations of all the standard query operators that LINQ to Objects supports, although it does not attempt to parallelize each one. Wenn Sie nicht mit LINQ vertraut sind, lesen Sie Einführung in LINQ (C#) und Einführung in LINQ (Visual Basic).If you are not familiar with LINQ, see Introduction to LINQ (C#) and Introduction to LINQ (Visual Basic).

Zusätzlich zu den Standardabfrageoperatoren enthält die ParallelEnumerable-Klasse einen Satz von Methoden, die spezielle Verhaltensweisen für die parallele Ausführung unterstützen.In addition to the standard query operators, the ParallelEnumerable class contains a set of methods that enable behaviors specific to parallel execution. Diese PLINQ-spezifischen Methoden sind in der folgenden Tabelle aufgeführt.These PLINQ-specific methods are listed in the following table.

ParallelEnumerable-OperatorParallelEnumerable Operator BeschreibungDescription
AsParallel Der Einstiegspunkt für PLINQ.The entry point for PLINQ. Gibt an, dass der Rest der Abfrage nach Möglichkeit parallelisiert werden soll.Specifies that the rest of the query should be parallelized, if it is possible.
AsSequential Gibt an, dass der Rest der Abfrage sequenziell, als nicht parallele LINQ-Abfrage ausgeführt werden soll.Specifies that the rest of the query should be run sequentially, as a non-parallel LINQ query.
AsOrdered Gibt an, diese PLINQ die Reihenfolge der Quellsequenz im Rest der Abfrage oder bis zu einer Änderung der Reihenfolge, z. B. durch eine orderby-Klausel (Ordner By in Vlsual Basic), beibehalten soll.Specifies that PLINQ should preserve the ordering of the source sequence for the rest of the query, or until the ordering is changed, for example by the use of an orderby (Order By in Visual Basic) clause.
AsUnordered Gibt an, dass PLINQ die Reihenfolge der Quellsequenz im Rest der Abfrage nicht beibehalten muss.Specifies that PLINQ for the rest of the query is not required to preserve the ordering of the source sequence.
WithCancellation Gibt an, diese PLINQ den Zustand des bereitgestellten Abbruchtokens in regelmäßigen Abständen überwachen und die Ausführung auf Anforderung abbrechen soll.Specifies that PLINQ should periodically monitor the state of the provided cancellation token and cancel execution if it is requested.
WithDegreeOfParallelism Gibt die maximale Anzahl von Prozessoren an, die PLINQ zum Parallelisieren der Abfrage verwenden soll.Specifies the maximum number of processors that PLINQ should use to parallelize the query.
WithMergeOptions Gibt an, wie PLINQ parallele Ergebnisse im Consumerthread wieder in einer Sequenz zusammenführen soll, sofern dies möglich ist.Provides a hint about how PLINQ should, if it is possible, merge parallel results back into just one sequence on the consuming thread.
WithExecutionMode Gibt an, ob PLINQ die Abfrage parallelisieren soll, selbst wenn diese standardmäßig sequenziell ausgeführt würde.Specifies whether PLINQ should parallelize the query even when the default behavior would be to run it sequentially.
ForAll Eine Multithreadenumerationsmethode, die, im Gegensatz zum Durchlaufen der Ergebnisse der Abfrage, eine parallele Verarbeitung der Ergebnisse ermöglicht, ohne dass diese zuvor im Consumerthread zusammengeführt werden.A multithreaded enumeration method that, unlike iterating over the results of the query, enables results to be processed in parallel without first merging back to the consumer thread.
Aggregate-ÜberladungAggregate overload Eine spezielle Überladung für PLINQ, die eine Zwischenaggregation über lokale Threadpartitionen sowie eine abschließende Aggregationsfunktion zum Kombinieren der Ergebnisse aller Partitionen ermöglicht.An overload that is unique to PLINQ and enables intermediate aggregation over thread-local partitions, plus a final aggregation function to combine the results of all partitions.

Das Opt-in-ModellThe Opt-in Model

Beim Schreiben einer Abfrage entscheiden Sie sich für PLINQ, indem Sie in der Datenquelle die ParallelEnumerable.AsParallel-Erweiterungsmethode aufrufen, wie im folgenden Beispiel gezeigt.When you write a query, opt in to PLINQ by invoking the ParallelEnumerable.AsParallel extension method on the data source, as shown in the following example.

var source = Enumerable.Range(1, 10000);

// Opt in to PLINQ with AsParallel.
var evenNums = from num in source.AsParallel()
               where num % 2 == 0
               select num;
Console.WriteLine("{0} even numbers out of {1} total",
                  evenNums.Count(), source.Count());
// The example displays the following output:
//       5000 even numbers out of 10000 total
Dim source = Enumerable.Range(1, 10000)

' Opt in to PLINQ with AsParallel
Dim evenNums = From num In source.AsParallel()
               Where num Mod 2 = 0
               Select num
Console.WriteLine("{0} even numbers out of {1} total",
                  evenNums.Count(), source.Count())
' The example displays the following output:
'       5000 even numbers out of 10000 total      

Die AsParallel-Erweiterungsmethode bindet die nachfolgenden Abfrageoperatoren, in diesem Fall, where und select, an die System.Linq.ParallelEnumerable-Implementierungen.The AsParallel extension method binds the subsequent query operators, in this case, where and select, to the System.Linq.ParallelEnumerable implementations.

AusführungsmodiExecution Modes

Standardmäßig wird PLINQ konservativ ausgeführt.By default, PLINQ is conservative. Die PLINQ-Infrastruktur analysiert zur Laufzeit die Gesamtstruktur der Abfrage.At run time, the PLINQ infrastructure analyzes the overall structure of the query. Wenn die Abfrage voraussichtlich durch eine Parallelisierung beschleunigt werden kann, partitioniert PLINQ die Quellsequenz in Aufgaben, die gleichzeitig ausgeführt werden können.If the query is likely to yield speedups by parallelization, PLINQ partitions the source sequence into tasks that can be run concurrently. Kann eine Abfrage nicht sicher parallelisiert werden, führt PLINQ die Abfrage sequenziell aus.If it is not safe to parallelize a query, PLINQ just runs the query sequentially. Wenn PLINQ die Wahl zwischen einem potenziell rechenintensiven parallelen Algorithmus und einem einfachen sequenziellen Algorithmus hat, entscheidet es sich standardmäßig für den sequenziellen Algorithmus.If PLINQ has a choice between a potentially expensive parallel algorithm or an inexpensive sequential algorithm, it chooses the sequential algorithm by default. Mit der WithExecutionMode-Methode und der System.Linq.ParallelExecutionMode-Enumeration können Sie PLINQ anweisen, den parallelen Algorithmus auszuwählen.You can use the WithExecutionMode method and the System.Linq.ParallelExecutionMode enumeration to instruct PLINQ to select the parallel algorithm. Dies ist sinnvoll, wenn Sie aufgrund von Tests und Messungen wissen, dass eine bestimmte Abfrage im parallelen Modus schneller ausgeführt wird.This is useful when you know by testing and measurement that a particular query executes faster in parallel. Weitere Informationen finden Sie unter Vorgehensweise: Angeben des Ausführungsmodus in PLINQ.For more information, see How to: Specify the Execution Mode in PLINQ.

Grad der ParallelitätDegree of Parallelism

Standardmäßig verwendet PLINQ alle Prozessoren des Hostcomputers.By default, PLINQ uses all of the processors on the host computer. Mit der WithDegreeOfParallelism-Methode können Sie PLINQ anweisen, nicht mehr als eine angegebene Anzahl von Prozessoren zu verwenden.You can instruct PLINQ to use no more than a specified number of processors by using the WithDegreeOfParallelism method. Sie können so sicherstellen, dass andere auf dem Computer ausgeführt Prozesse eine bestimmte Menge an CPU-Zeit erhalten.This is useful when you want to make sure that other processes running on the computer receive a certain amount of CPU time. Der folgende Codeausschnitt beschränkt die Abfrage auf maximal zwei Prozessoren.The following snippet limits the query to utilizing a maximum of two processors.

var query = from item in source.AsParallel().WithDegreeOfParallelism(2)
            where Compute(item) > 42
            select item;
Dim query = From item In source.AsParallel().WithDegreeOfParallelism(2)
            Where Compute(item) > 42
            Select item

Wenn eine Abfrage eine große Mengen an nicht rechnergebundenen Aufgaben ausführt, z. B. Datei-E/A, kann es von Vorteil sein, einen höheren Grad an Parallelität als die auf dem Rechner verfügbare Anzahl von Kernen anzugeben.In cases where a query is performing a significant amount of non-compute-bound work such as File I/O, it might be beneficial to specify a degree of parallelism greater than the number of cores on the machine.

Geordnete und ungeordnete parallele AbfragenOrdered Versus Unordered Parallel Queries

Bei einigen Abfragen muss ein Abfrageoperator Ergebnisse erzeugen, die die Reihenfolge der Quellsequenz beibehalten.In some queries, a query operator must produce results that preserve the ordering of the source sequence. PLINQ stellt für diesen Zweck den AsOrdered-Operator bereit.PLINQ provides the AsOrdered operator for this purpose. AsOrdered unterscheidet sich von AsSequential.AsOrdered is distinct from AsSequential. Eine AsOrdered-Sequenz wird weiterhin parallel ausgeführt, die Ergebnisse werden jedoch gepuffert und sortiert.An AsOrdered sequence is still processed in parallel, but its results are buffered and sorted. Da die Beibehaltung der Reihenfolge in der Regel einen gewissen Mehraufwand bedeutet, wird eine AsOrdered-Sequenz ggf. langsamer verarbeitet als die standardmäßige AsUnordered-Sequenz.Because order preservation typically involves extra work, an AsOrdered sequence might be processed more slowly than the default AsUnordered sequence. Ob ein bestimmter geordneter paralleler Vorgang schneller ist als eine sequenzielle Version des Vorgangs, hängt von vielen Faktoren ab.Whether a particular ordered parallel operation is faster than a sequential version of the operation depends on many factors.

Im folgenden Codebeispiel wird gezeigt, wie Sie die Beibehaltung der Reihenfolge aktivieren.The following code example shows how to opt in to order preservation.

var evenNums = from num in numbers.AsParallel().AsOrdered()
              where num % 2 == 0
              select num;
Dim evenNums = From num In numbers.AsParallel().AsOrdered()
               Where num Mod 2 = 0
               Select num


Weitere Informationen finden Sie unter Order Preservation in PLINQ (Beibehaltung der Reihenfolge in PLINQ).For more information, see Order Preservation in PLINQ.

Parallele und sequenzielle AbfragenParallel vs. Sequential Queries

Einige Vorgänge erfordern, dass die Quelldaten sequenziell übergeben werden.Some operations require that the source data be delivered in a sequential manner. Die ParallelEnumerable-Abfrageoperatoren stellen automatisch den sequenziellen Modus wieder her, wenn dies erforderlich ist.The ParallelEnumerable query operators revert to sequential mode automatically when it is required. Für benutzerdefinierte Abfrageoperatoren und Benutzerdelegaten, die eine sequenzielle Ausführung erfordern, stellt PLINQ die AsSequential-Methode bereit.For user-defined query operators and user delegates that require sequential execution, PLINQ provides the AsSequential method. Bei Verwendung von AsSequential werden alle nachfolgenden Operatoren in der Abfrage sequenziell ausgeführt, bis AsParallel erneut aufgerufen wird.When you use AsSequential, all subsequent operators in the query are executed sequentially until AsParallel is called again. Weitere Informationen finden Sie unter Vorgehensweise: Kombinieren von parallelen und sequenziellen LINQ-Abfragen.For more information, see How to: Combine Parallel and Sequential LINQ Queries.

Optionen für das Zusammenführen von AbfrageergebnissenOptions for Merging Query Results

Wenn eine PLINQ-Abfrage parallel ausgeführt wird, müssen die Ergebnisse aller Arbeitsthreads wieder im Hauptthread zusammengeführt werden, damit sie in einer foreach-Schleife (For Each in Visual Basics) verwendet oder in eine Liste bzw. ein Array eingefügt werden können.When a PLINQ query executes in parallel, its results from each worker thread must be merged back onto the main thread for consumption by a foreach loop (For Each in Visual Basic), or insertion into a list or array. In einigen Fällen ist es hilfreich, eine bestimmte Art von Merge anzugeben, z. B. um Ergebnisse schneller zu erzeugen.In some cases, it might be beneficial to specify a particular kind of merge operation, for example, to begin producing results more quickly. Zu diesem Zweck unterstützt PLINQ die WithMergeOptions-Methode und die ParallelMergeOptions-Enumeration.For this purpose, PLINQ supports the WithMergeOptions method, and the ParallelMergeOptions enumeration. Weitere Informationen finden Sie unter Merge Options in PLINQ (Zusammenführungsoptionen in PLINQ).For more information, see Merge Options in PLINQ.

Der ForAll-OperatorThe ForAll Operator

In sequenziellen LINQ-Abfragen wird die Ausführung verzögert, bis die Abfrage entweder in einer foreach-Schleife (For Each in Visual Basic) oder durch das Aufrufen einer Methode, z. B. ToList, ToArray oder ToDictionary, aufgezählt wird.In sequential LINQ queries, execution is deferred until the query is enumerated either in a foreach (For Each in Visual Basic) loop or by invoking a method such as ToList , ToArray , or ToDictionary. In PLINQ können Sie zudem foreach verwenden, um die Abfrage auszuführen und die Ergebnisse zu durchlaufen.In PLINQ, you can also use foreach to execute the query and iterate through the results. foreach selbst wird jedoch nicht parallel ausgeführt, sodass die Ausgabe aller parallelen Aufgaben wieder in dem Thread, in dem die Schleife ausgeführt wird, zusammengeführt werden muss.However, foreach itself does not run in parallel, and therefore, it requires that the output from all parallel tasks be merged back into the thread on which the loop is running. In PLINQ können Sie foreach verwenden, wenn Sie die abschließende Reihenfolge der Abfrageergebnisse beibehalten möchten oder wenn Sie die Ergebnisse seriell verarbeiten, z. B. wenn Sie für jedes Element Console.WriteLine aufrufen.In PLINQ, you can use foreach when you must preserve the final ordering of the query results, and also whenever you are processing the results in a serial manner, for example when you are calling Console.WriteLine for each element. Wenn die Beibehaltung der Reihenfolge nicht erforderlich ist und die Verarbeitung der Ergebnisse selbst parallelisiert werden kann, verwenden Sie die ForAll-Methode, um die Ausführung der PLINQ-Abfrage zu beschleunigen.For faster query execution when order preservation is not required and when the processing of the results can itself be parallelized, use the ForAll method to execute a PLINQ query. ForAll führt die abschließende Zusammenführung nicht aus.ForAll does not perform this final merge step. Im folgenden Codebeispiel wird die Verwendung der ForAll-Methode veranschaulicht.The following code example shows how to use the ForAll method. System.Collections.Concurrent.ConcurrentBag<T> wird hier verwendet, da sie für mehrere Threads optimiert ist, die gleichzeitig Elemente hinzufügen, ohne dass versucht wird, Elemente zu entfernen.System.Collections.Concurrent.ConcurrentBag<T> is used here because it is optimized for multiple threads adding concurrently without attempting to remove any items.

var nums = Enumerable.Range(10, 10000);
var query = from num in nums.AsParallel()
            where num % 10 == 0
            select num;

// Process the results as each thread completes
// and add them to a System.Collections.Concurrent.ConcurrentBag(Of Int)
// which can safely accept concurrent add operations
query.ForAll(e => concurrentBag.Add(Compute(e)));
Dim nums = Enumerable.Range(10, 10000)
Dim query = From num In nums.AsParallel()
            Where num Mod 10 = 0
            Select num

' Process the results as each thread completes
' and add them to a System.Collections.Concurrent.ConcurrentBag(Of Int)
' which can safely accept concurrent add operations
query.ForAll(Sub(e) concurrentBag.Add(Compute(e)))

Die folgende Abbildung zeigt den Unterschied zwischen foreach und ForAll hinsichtlich der Abfrageausführung.The following illustration shows the difference between foreach and ForAll with regard to query execution.

ForAll im Vergleich zu ForEachForAll vs. ForEach

AbbruchCancellation

PLINQ ist in die Abbruchtypen in .NET Framework 4 integriert.PLINQ is integrated with the cancellation types in .NET Framework 4. (Weitere Informationen finden Sie unter Cancellation in Managed Threads (Abbruch in verwalteten Threads).) Daher können PLINQ-Abfragen im Gegensatz zu sequenziellen LINQ to Objects-Abfragen abgebrochen werden.(For more information, see Cancellation in Managed Threads.) Therefore, unlike sequential LINQ to Objects queries, PLINQ queries can be canceled. Um eine abbrechbare PLINQ-Abfrage zu erstellen, verwenden Sie den WithCancellation-Operator in der Abfrage, und stellen Sie eine CancellationToken-Instanz als Argument bereit.To create a cancelable PLINQ query, use the WithCancellation operator on the query and provide a CancellationToken instance as the argument. Wenn die IsCancellationRequested-Eigenschaft im Token auf „true“ festgelegt ist, erkennt PLINQ dies. Die Verarbeitung wird in diesem Fall in allen Threads abgebrochen, und eine OperationCanceledException wird ausgelöst.When the IsCancellationRequested property on the token is set to true, PLINQ will notice it, stop processing on all threads, and throw an OperationCanceledException.

Es ist möglich, dass eine PLINQ-Abfrage nach dem Festlegen des Abbruchtokens weiterhin einige Elemente verarbeitet.It is possible that a PLINQ query might continue to process some elements after the cancellation token is set.

Um kürzere Reaktionszeiten zu erzielen, können Sie auch auf Abbruchanforderungen in Benutzerdelegaten mit langer Laufzeit reagieren.For greater responsiveness, you can also respond to cancellation requests in long-running user delegates. Weitere Informationen finden Sie unter Vorgehensweise: Abbrechen einer PLINQ-Abfrage.For more information, see How to: Cancel a PLINQ Query.

AusnahmenExceptions

Bei der Ausführung einer PLINQ-Abfrage können mehrere Ausnahmen von verschiedenen Threads gleichzeitig ausgelöst werden.When a PLINQ query executes, multiple exceptions might be thrown from different threads simultaneously. Zudem kann sich der Code für die Behandlung einer Ausnahme in einem anderen Thread befinden als der Code, der die Ausnahme ausgelöst hat.Also, the code to handle the exception might be on a different thread than the code that threw the exception. PLINQ kapselt alle Ausnahmen, die von einer Abfrage ausgelöst wurden, mithilfe des AggregateException-Typs und marshallt diese Ausnahmen zurück an den aufrufenden Thread.PLINQ uses the AggregateException type to encapsulate all the exceptions that were thrown by a query, and marshal those exceptions back to the calling thread. Im aufrufenden Thread ist nur ein try/catch-Block erforderlich.On the calling thread, only one try-catch block is required. Sie können jedoch alle Ausnahmen durchlaufen, die in AggregateException gekapselt sind, und die Ausnahmen erfassen, die Sie sicher beheben können.However, you can iterate through all of the exceptions that are encapsulated in the AggregateException and catch any that you can safely recover from. In seltenen Fällen können Ausnahmen ausgelöst werden, die nicht in einer AggregateException eingeschlossen sind. ThreadAbortExceptions sind ebenfalls nicht eingeschlossen.In rare cases, some exceptions may be thrown that are not wrapped in an AggregateException, and ThreadAbortExceptions are also not wrapped.

Wenn Ausnahmen mittels Bubbling wieder an den Verbindungsthread übergeben werden können, ist es möglich, dass eine Abfrage nach dem Auslösen der Ausnahme weiterhin einige Elemente verarbeitet.When exceptions are allowed to bubble up back to the joining thread, then it is possible that a query may continue to process some items after the exception is raised.

Weitere Informationen finden Sie unter Vorgehensweise: Behandeln von Ausnahmen in einer PLINQ-Abfrage.For more information, see How to: Handle Exceptions in a PLINQ Query.

Benutzerdefinierte PartitioniererCustom Partitioners

Sie können die Abfrageleistung teilweise erhöhen, indem Sie einen benutzerdefinierten Partitionierer schreiben, der bestimmte Merkmale der Quelldaten nutzt.In some cases, you can improve query performance by writing a custom partitioner that takes advantage of some characteristic of the source data. In der Abfrage ist der benutzerdefinierte Partitionierer das auflistbare Objekt, das abgefragt wird.In the query, the custom partitioner itself is the enumerable object that is queried.

int[] arr = new int[9999];
Partitioner<int> partitioner = new MyArrayPartitioner<int>(arr);
var query = partitioner.AsParallel().Select(x => SomeFunction(x));
Dim arr(10000) As Integer
Dim partitioner As Partitioner(Of Integer) = New MyArrayPartitioner(Of Integer)(arr)
Dim query = partitioner.AsParallel().Select(Function(x) SomeFunction(x))

PLINQ unterstützt eine feste Anzahl von Partitionen (auch wenn die Daten während der Laufzeit diesen Partitionen dynamisch neu zugeordnet werden können, um einen Lastenausgleich zu gewährleisten).PLINQ supports a fixed number of partitions (although data may be dynamically reassigned to those partitions during run time for load balancing.). For und ForEach unterstützen nur die dynamische Partitionierung, d. h. die Anzahl der Partitionen ändert sich zur Laufzeit.For and ForEach support only dynamic partitioning, which means that the number of partitions changes at run time. Weitere Informationen finden Sie unter Custom Partitioners for PLINQ and TPL (Benutzerdefinierte Partitionierer für PLINQ und TPL).For more information, see Custom Partitioners for PLINQ and TPL.

Messen der PLINQ-LeistungMeasuring PLINQ Performance

In vielen Fällen kann eine Abfrage parallelisiert werden, der mit dem Einrichten der parallelen Abfrage verbundene Mehraufwand überwiegt jedoch die erzielte Leistungssteigerung.In many cases, a query can be parallelized, but the overhead of setting up the parallel query outweighs the performance benefit gained. Wenn eine Abfrage nur wenige Berechnung ausführt oder wenn die Datenquelle klein ist, ist eine PLINQ-Abfrage möglicherweise langsamer als ein sequenzielle LINQ to Objects-Abfrage.If a query does not perform much computation or if the data source is small, a PLINQ query may be slower than a sequential LINQ to Objects query. Mithilfe des Parallel Performance Analyzer in Visual Studio Team Server können Sie die Leistung verschiedener Abfragen vergleichen, Verarbeitungsengpässe suchen und bestimmen, ob die Abfrage parallel oder sequenziell ausgeführt wird.You can use the Parallel Performance Analyzer in Visual Studio Team Server to compare the performance of various queries, to locate processing bottlenecks, and to determine whether your query is running in parallel or sequentially. Weitere Informationen finden Sie unter Parallelitätsschnellansicht und Vorgehensweise: Messen der Leistung von PLINQ-Abfragen.For more information, see Concurrency Visualizer and How to: Measure PLINQ Query Performance.

Siehe auchSee also