Introduzione a PLINQIntroduction to PLINQ

Parallel LINQ (PLINQ) è un'implementazione parallela del modello LINQ (Language-Integrated Query) .Parallel LINQ (PLINQ) is a parallel implementation of the Language-Integrated Query (LINQ) pattern. PLINQ implementa il set completo di operatori di query standard LINQ come metodi di estensione per lo spazio dei nomi System.Linq e dispone di operatori aggiuntivi per le operazioni parallele.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 combina la semplicità e la leggibilità della sintassi di LINQ con la potenza di programmazione in parallelo.PLINQ combines the simplicity and readability of LINQ syntax with the power of parallel programming.

Suggerimento

Se non si ha familiarità con LINQ, offre un modello unificato per l'esecuzione di query su qualsiasi origine dati enumerabile in modo indipendente dai tipi.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 è il nome delle query LINQ eseguite su raccolte in memoria, ad esempio oggetti List<T> e matrici.LINQ to Objects is the name for LINQ queries that are run against in-memory collections such as List<T> and arrays. Questo articolo presuppone che si abbia già una conoscenza delle nozioni di base di LINQ.This article assumes that you have a basic understanding of LINQ. Per ulteriori informazioni, vedere LINQ (Language-Integrated Query).For more information, see Language-Integrated Query (LINQ).

Che cos'è una query parallela?What is a Parallel query?

Una query PLINQ è molto simile a una query LINQ to Objects non parallela.A PLINQ query in many ways resembles a non-parallel LINQ to Objects query. Le query PLINQ, esattamente come le query LINQ sequenziali, operano su IEnumerable qualsiasi IEnumerable<T> origine dati o in memoria e hanno un'esecuzione posticipata, il che significa che non iniziano l'esecuzione fino a quando la query non viene enumerata.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. La differenza principale consiste nel fatto che PLINQ tenta di sfruttare al massimo tutti i processori del sistema.The primary difference is that PLINQ attempts to make full use of all the processors on the system. A tale scopo esegue il partizionamento dell'origine dati in segmenti e quindi esegue la query su ogni segmento in thread di lavoro distinti e in parallelo su più processori.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 molti casi, l'esecuzione parallela rende notevolmente più rapida l'esecuzione della query.In many cases, parallel execution means that the query runs significantly faster.

Tramite l'esecuzione parallela, PLINQ può garantire per determinati tipi di query prestazioni significativamente migliori rispetto al codice legacy, spesso con la sola aggiunta dell'operazione di query AsParallel all'origine dati.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. Tuttavia, il parallelismo può introdurre complessità intrinseche e non tutte le operazioni di query presentano un'esecuzione più veloce in PLINQ.However, parallelism can introduce its own complexities, and not all query operations run faster in PLINQ. Di fatto, per determinate query la parallelizzazione comporta un'esecuzione più lenta.In fact, parallelization actually slows down certain queries. È pertanto necessario comprendere il modo in cui alcuni aspetti, ad esempio l'ordinamento, influiscono sulle query parallele.Therefore, you should understand how issues such as ordering affect parallel queries. Per altre informazioni, vedere Informazioni sull'aumento di velocità in PLINQ.For more information, see Understanding Speedup in PLINQ.

Nota

Le espressioni lambda sono usate nella documentazione per definire i delegati in PLINQ.This documentation uses lambda expressions to define delegates in PLINQ. Se non si ha familiarità con le espressioni lambda in C# o Visual Basic, vedere espressioni lambda in PLINQ e TPL.If you are not familiar with lambda expressions in C# or Visual Basic, see Lambda Expressions in PLINQ and TPL.

Nella parte restante di questo articolo viene fornita una panoramica delle classi PLINQ principali e viene illustrato come creare query PLINQ.The remainder of this article gives an overview of the main PLINQ classes and discusses how to create PLINQ queries. Ogni sezione contiene collegamenti a informazioni dettagliate ed esempi di codice.Each section contains links to more detailed information and code examples.

Classe ParallelEnumerableThe ParallelEnumerable Class

La classe System.Linq.ParallelEnumerable espone quasi tutte le funzionalità di PLINQ.The System.Linq.ParallelEnumerable class exposes almost all of PLINQ's functionality. Questa classe e gli altri tipi dello spazio dei nomi System.Linq vengono compilati nell'assembly System.Core.dll.It and the rest of the System.Linq namespace types are compiled into the System.Core.dll assembly. In Visual Studio i progetti C# e Visual Basic predefiniti fanno riferimento all'assembly e importano lo spazio dei nomi.The default C# and Visual Basic projects in Visual Studio both reference the assembly and import the namespace.

ParallelEnumerable include le implementazioni di tutti gli operatori query standard supportati da LINQ to Objects, anche se non tenta di parallelizzare ognuno di essi.ParallelEnumerable includes implementations of all the standard query operators that LINQ to Objects supports, although it does not attempt to parallelize each one. Se non si ha familiarità con LINQ, vedere Introduzione a LINQ (C#) e Introduzione a LINQ (Visual Basic).If you are not familiar with LINQ, see Introduction to LINQ (C#) and Introduction to LINQ (Visual Basic).

Oltre agli operatori query standard, la classe ParallelEnumerable contiene un set di metodi che rendono possibili comportamenti specifici dell'esecuzione parallela.In addition to the standard query operators, the ParallelEnumerable class contains a set of methods that enable behaviors specific to parallel execution. Questi metodi specifici di PLINQ sono elencati nella tabella seguente.These PLINQ-specific methods are listed in the following table.

Operatore ParallelEnumerableParallelEnumerable Operator DescrizioneDescription
AsParallel Punto di ingresso di PLINQ.The entry point for PLINQ. Specifica che la parte rimanente della query deve essere parallelizzata, se è possibile.Specifies that the rest of the query should be parallelized, if it is possible.
AsSequential Specifica che la parte rimanente della query deve essere eseguita in sequenza, come una query LINQ non parallela.Specifies that the rest of the query should be run sequentially, as a non-parallel LINQ query.
AsOrdered Specifica che PLINQ deve conservare l'ordine della sequenza di origine per la parte rimanente della query oppure fino a quando l'ordine non viene modificato, ad esempio tramite la clausola orderby (Order By in Visual Basic).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 Specifica che non è necessario che PLINQ conservi l'ordine della sequenza di origine per la parte rimanente della query.Specifies that PLINQ for the rest of the query is not required to preserve the ordering of the source sequence.
WithCancellation Specifica che PLINQ deve monitorare periodicamente lo stato del token di annullamento specificato e, se richiesto, annullare l'esecuzione.Specifies that PLINQ should periodically monitor the state of the provided cancellation token and cancel execution if it is requested.
WithDegreeOfParallelism Specifica il numero massimo di processori che PLINQ deve usare per parallelizzare la query.Specifies the maximum number of processors that PLINQ should use to parallelize the query.
WithMergeOptions Offre un suggerimento su come PLINQ deve unire, se possibile, i risultati paralleli in un'unica sequenza nel thread in uso.Provides a hint about how PLINQ should, if it is possible, merge parallel results back into just one sequence on the consuming thread.
WithExecutionMode Specifica se PLINQ deve parallelizzare la query anche quando il comportamento predefinito ne prevede l'esecuzione sequenziale.Specifies whether PLINQ should parallelize the query even when the default behavior would be to run it sequentially.
ForAll Metodo di enumerazione multithreading che, a differenza dell'iterazione sui risultati della query, consente ai risultati di essere elaborati in parallelo senza prima essere uniti nel thread in uso.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.
Overload AggregateAggregate overload Overload esclusivo di PLINQ che consente l'aggregazione intermedia su partizioni di thread locali e che offre una funzione di aggregazione finale per combinare i risultati di tutte le partizioni.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.

Modello basato su scelta esplicitaThe Opt-in Model

Quando si scrive una query è possibile scegliere esplicitamente PLINQ richiamando il metodo di estensione ParallelEnumerable.AsParallel nell'origine dati, come illustrato nell'esempio seguente.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      

Il metodo di estensione AsParallel associa gli operatori di query successivi, in questo caso where e select, alle implementazioni di System.Linq.ParallelEnumerable.The AsParallel extension method binds the subsequent query operators, in this case, where and select, to the System.Linq.ParallelEnumerable implementations.

Modalità di esecuzioneExecution Modes

Per impostazione predefinita, PLINQ è conservativo.By default, PLINQ is conservative. Durante il runtime, l'infrastruttura PLINQ analizza la struttura complessiva della query.At run time, the PLINQ infrastructure analyzes the overall structure of the query. Se è probabile che la parallelizzazione della query comporti una maggiore velocità di esecuzione, PLINQ esegue il partizionamento della sequenza di origine in attività eseguibili simultaneamente.If the query is likely to yield speedups by parallelization, PLINQ partitions the source sequence into tasks that can be run concurrently. Se la parallelizzazione della query non risulta un'operazione sicura, PLINQ si limita ad eseguire la query in modo sequenziale.If it is not safe to parallelize a query, PLINQ just runs the query sequentially. Tra un algoritmo in parallelo potenzialmente dispendioso e un algoritmo sequenziale poco dispendioso, per impostazione predefinita PLINQ sceglie l'algoritmo sequenziale.If PLINQ has a choice between a potentially expensive parallel algorithm or an inexpensive sequential algorithm, it chooses the sequential algorithm by default. È possibile usare il metodo WithExecutionMode e l'enumerazione System.Linq.ParallelExecutionMode per indicare a PLINQ di selezionare l'algoritmo parallelo.You can use the WithExecutionMode method and the System.Linq.ParallelExecutionMode enumeration to instruct PLINQ to select the parallel algorithm. Ciò è utile quando si scopre tramite test e misurazioni che una determinata query risulta più veloce quando viene eseguita in parallelo.This is useful when you know by testing and measurement that a particular query executes faster in parallel. Per altre informazioni, vedere Procedura: Specificare la modalità di esecuzione in PLINQ.For more information, see How to: Specify the Execution Mode in PLINQ.

Grado di parallelismoDegree of Parallelism

Per impostazione predefinita, PLINQ usa tutti i processori nel computer host.By default, PLINQ uses all of the processors on the host computer. Usando il metodo WithDegreeOfParallelism è possibile indicare a PLINQ di usare un numero massimo di processori specificato.You can instruct PLINQ to use no more than a specified number of processors by using the WithDegreeOfParallelism method. Ciò è utile quando si vuole garantire che gli altri processi in esecuzione nel computer ricevano una determinata quantità di tempo CPU.This is useful when you want to make sure that other processes running on the computer receive a certain amount of CPU time. Il frammento seguente consente alla query di usare al massimo due processori.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

Nei casi in cui una query stia eseguendo una quantità significativa di lavoro privo di vincoli di calcolo, ad esempio l'I/O dei file, può risultare vantaggioso specificare un grado di parallelismo maggiore del numero di core nel computer.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.

Confronto fra query parallele ordinate e non ordinateOrdered Versus Unordered Parallel Queries

In alcune query l'operatore di query deve produrre risultati che conservano l'ordine della sequenza di origine.In some queries, a query operator must produce results that preserve the ordering of the source sequence. A questo scopo, PLINQ fornisce l'operatore AsOrdered.PLINQ provides the AsOrdered operator for this purpose. AsOrdered si differenzia da AsSequential.AsOrdered is distinct from AsSequential. Una sequenza AsOrdered viene comunque elaborata in parallelo, ma i risultati vengono memorizzati nel buffer e ordinati.An AsOrdered sequence is still processed in parallel, but its results are buffered and sorted. Poiché la conservazione dell'ordine comporta in genere un lavoro aggiuntivo, è possibile che una sequenza AsOrdered venga elaborata più lentamente rispetto alla sequenza AsUnordered predefinita.Because order preservation typically involves extra work, an AsOrdered sequence might be processed more slowly than the default AsUnordered sequence. La possibilità che una determinata operazione in parallelo ordinata risulti più veloce di una versione sequenziale dell'operazione dipende da molti fattori.Whether a particular ordered parallel operation is faster than a sequential version of the operation depends on many factors.

L'esempio di codice seguente illustra come scegliere esplicitamente la conservazione dell'ordine.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


Per altre informazioni, vedere Conservazione dell'ordine in PLINQ.For more information, see Order Preservation in PLINQ.

Query parallele e sequenzialiParallel vs. Sequential Queries

Alcune operazioni richiedono che i dati di origine vengano recapitati in modo sequenziale.Some operations require that the source data be delivered in a sequential manner. Quando è necessario, gli operatori di query ParallelEnumerable ripristinano automaticamente la modalità sequenziale.The ParallelEnumerable query operators revert to sequential mode automatically when it is required. Per gli operatori di query definiti dall'utente e i delegati dell'utente che richiedono l'esecuzione sequenziale, PLINQ fornisce il metodo AsSequential.For user-defined query operators and user delegates that require sequential execution, PLINQ provides the AsSequential method. Quando si usa AsSequential, tutti gli operatori successivi nella query vengono eseguiti in sequenza fino a quando non viene richiamato il metodo AsParallel.When you use AsSequential, all subsequent operators in the query are executed sequentially until AsParallel is called again. Per altre informazioni, vedere Procedura: Combinare query LINQ parallele e sequenziali.For more information, see How to: Combine Parallel and Sequential LINQ Queries.

Opzioni di unione dei risultati di queryOptions for Merging Query Results

Quando una query PLINQ viene eseguita in parallelo, i relativi risultati ottenuti da ogni thread di lavoro devono essere uniti nel thread principale affinché vengano usati da un ciclo foreach (For Each in Visual Basic) o vengano inseriti in un elenco o in una matrice.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 alcuni casi può essere vantaggioso specificare un determinato tipo di operazione di unione, ad esempio per iniziare a produrre risultati più velocemente.In some cases, it might be beneficial to specify a particular kind of merge operation, for example, to begin producing results more quickly. A tale scopo, PLINQ supporta il metodo WithMergeOptions e l'enumerazione ParallelMergeOptions.For this purpose, PLINQ supports the WithMergeOptions method, and the ParallelMergeOptions enumeration. Per altre informazioni, vedere Opzioni di unione in PLINQ.For more information, see Merge Options in PLINQ.

Operatore ForAllThe ForAll Operator

Nelle query LINQ sequenziali l'esecuzione viene posticipata fino a quando la query non viene enumerata in un foreach For Each ciclo (in Visual Basic) o richiamando un metodo come ToList , ToArray o ToDictionary .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 è anche possibile usare foreach per eseguire la query e l'iterazione dei risultati.In PLINQ, you can also use foreach to execute the query and iterate through the results. Tuttavia, poiché non viene eseguito in parallelo, foreach richiede che l'output di tutte le attività in parallelo venga unito di nuovo nel thread in cui il ciclo è in esecuzione.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 è possibile usare foreach quando è necessario conservare l'ordine finale dei risultati della query nonché quando si elaborano i risultati in modo seriale, ad esempio quando si chiama Console.WriteLine per ogni elemento.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. Per eseguire più velocemente una query quando la conservazione dell'ordine non è richiesta e quando la stessa elaborazione dei risultati può essere parallelizzata, usare il metodo ForAll per eseguire una query PLINQ.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 non esegue questo passaggio di merge finale.ForAll does not perform this final merge step. Nell'esempio di codice riportato di seguito viene illustrato come utilizzare il metodo ForAll.The following code example shows how to use the ForAll method. In questo caso viene usato l'oggetto System.Collections.Concurrent.ConcurrentBag<T> perché è ottimizzato per l'aggiunta simultanea di più thread senza un tentativo di rimuovere gli elementi.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)))

La figura seguente mostra la differenza tra foreach e ForAll per quanto riguarda l'esecuzione di query.The following illustration shows the difference between foreach and ForAll with regard to query execution.

ForAll e ForEachForAll vs. ForEach

AnnullamentoCancellation

PLINQ è integrato con i tipi di annullamento in .NET Framework 4.PLINQ is integrated with the cancellation types in .NET Framework 4. Per ulteriori informazioni, vedere annullamento in thread gestiti. Pertanto, a differenza delle query di LINQ to Objects sequenziali, le query PLINQ possono essere annullate.(For more information, see Cancellation in Managed Threads.) Therefore, unlike sequential LINQ to Objects queries, PLINQ queries can be canceled. Per creare una query PLINQ annullabile, usare l'operatore WithCancellation nella query e fornire un'istanza di CancellationToken come argomento.To create a cancelable PLINQ query, use the WithCancellation operator on the query and provide a CancellationToken instance as the argument. Quando la proprietà IsCancellationRequested nel token è impostata su true, PLINQ rileva questa impostazione, arresta l'elaborazione in tutti i thread e genera un'eccezione OperationCanceledException.When the IsCancellationRequested property on the token is set to true, PLINQ will notice it, stop processing on all threads, and throw an OperationCanceledException.

È possibile che una query PLINQ continui a elaborare alcuni elementi dopo l'impostazione del token di annullamento.It is possible that a PLINQ query might continue to process some elements after the cancellation token is set.

Per garantire una maggiore capacità di risposta, è possibile rispondere alle richieste di annullamento anche nei delegati dell'utente di lunga durata.For greater responsiveness, you can also respond to cancellation requests in long-running user delegates. Per altre informazioni, vedere Procedura: Annullare una query PLINQ.For more information, see How to: Cancel a PLINQ Query.

EccezioniExceptions

Quando viene eseguita una query PLINQ, è possibile che vengano generate simultaneamente più eccezioni da thread diversi.When a PLINQ query executes, multiple exceptions might be thrown from different threads simultaneously. Inoltre, il codice per gestire l'eccezione e quello che ha generato l'eccezione potrebbero trovarsi in thread diversi.Also, the code to handle the exception might be on a different thread than the code that threw the exception. PLINQ usa il tipo AggregateException per incapsulare tutte le eccezioni generate da una query e quindi eseguirne il marshalling nel thread chiamante.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. Nel thread chiamante è necessario un unico blocco try-catch.On the calling thread, only one try-catch block is required. È possibile tuttavia eseguire l'iterazione in tutte le eccezioni incapsulate in AggregateException e rilevare quelle gestibili in modo sicuro.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 casi rari, alcune eccezioni possono essere generate senza wrapping in AggregateException. Anche ThreadAbortException non prevede il wrapping.In rare cases, some exceptions may be thrown that are not wrapped in an AggregateException, and ThreadAbortExceptions are also not wrapped.

Quando alle eccezioni è consentita la propagazione fino al thread di unione, è possibile che una query continui a elaborare alcuni elementi dopo la generazione dell'eccezione.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.

Per altre informazioni, vedere Procedura: Gestire le eccezioni in una query PLINQ.For more information, see How to: Handle Exceptions in a PLINQ Query.

Partitioner personalizzatiCustom Partitioners

In alcuni casi è possibile migliorare le prestazioni delle query scrivendo un Partitioner personalizzato che sfrutta alcune caratteristiche dei dati di origine.In some cases, you can improve query performance by writing a custom partitioner that takes advantage of some characteristic of the source data. Nella query il partitioner personalizzato è l'oggetto enumerabile su cui viene eseguita la query.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 supporta un numero fisso di partizioni. È tuttavia possibile che durante il runtime i dati vengano riassegnati dinamicamente alle partizioni per il bilanciamento del carico.PLINQ supports a fixed number of partitions (although data may be dynamically reassigned to those partitions during run time for load balancing.). For e ForEach supportano solo il partizionamento dinamico, il che significa che il numero di partizioni cambia in fase di esecuzione.For and ForEach support only dynamic partitioning, which means that the number of partitions changes at run time. Per altre informazioni, vedere Partitioner personalizzati per PLINQ e TPL.For more information, see Custom Partitioners for PLINQ and TPL.

Misurazione delle prestazioni di PLINQMeasuring PLINQ Performance

In molti casi una query può essere parallelizzata, ma le risorse necessarie per configurare la query parallela rappresentano uno svantaggio superiore al vantaggio ottenuto in termini di prestazioni.In many cases, a query can be parallelized, but the overhead of setting up the parallel query outweighs the performance benefit gained. Se la query esegue pochi calcoli o se l'origine dati è di dimensioni ridotte, è possibile che una query PLINQ risulti più lenta di una query LINQ to Objects sequenziale.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. È possibile usare Parallel Performance Analyzer in Visual Studio Team Server per confrontare le prestazioni delle diverse query per individuare colli di bottiglia di elaborazione e determinare se la query è eseguita in parallelo o in modo sequenziale.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. Per altre informazioni, vedere Visualizzatore di concorrenze e Procedura: Misurare le prestazioni di esecuzione delle query di PLINQ.For more information, see Concurrency Visualizer and How to: Measure PLINQ Query Performance.

Vedere ancheSee also