Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Quando una query viene eseguita come parallela, PLINQ partiziona la sequenza di origine in modo che più thread possano funzionare contemporaneamente su parti diverse, in genere su thread separati. Se i risultati devono essere utilizzati in un thread, ad esempio in un foreach ciclo (For Each in Visual Basic), i risultati di ogni thread devono essere uniti nuovamente in una sequenza. Il tipo di merge eseguito da PLINQ dipende dagli operatori presenti nella query. Ad esempio, gli operatori che impongono un nuovo ordine sui risultati devono memorizzare nel buffer tutti gli elementi di tutti i thread. Dal punto di vista del thread di utilizzo ,che è anche quello dell'utente dell'applicazione, una query completamente memorizzata nel buffer potrebbe essere eseguita per un periodo di tempo notevole prima che produca il primo risultato. Altri operatori, per impostazione predefinita, sono parzialmente memorizzati nel buffer; producono i loro risultati in batch. Un operatore, ForAll non viene memorizzato nel buffer per impostazione predefinita. Restituisce immediatamente tutti gli elementi di tutti i thread.
Usando il WithMergeOptions metodo , come illustrato nell'esempio seguente, è possibile fornire un suggerimento a PLINQ che indica il tipo di unione da eseguire.
var scanLines = from n in nums.AsParallel()
.WithMergeOptions(ParallelMergeOptions.NotBuffered)
where n % 2 == 0
select ExpensiveFunc(n);
Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
Where n Mod 2 = 0
Select ExpensiveFunc(n)
Per l'esempio completo, vedere Procedura: Specificare le opzioni di merge in PLINQ.
Se la query specifica non supporta l'opzione richiesta, l'opzione verrà semplicemente ignorata. Nella maggior parte dei casi, non è necessario specificare un'opzione di unione per una query PLINQ. Tuttavia, in alcuni casi è possibile che si verifichi testando e misurando che una query viene eseguita meglio in una modalità non predefinita. Un uso comune di questa opzione consiste nel forzare un operatore di unione blocchi a trasmettere i risultati per fornire un'interfaccia utente più reattiva.
Opzioni di Fusione Parallela (ParallelMergeOptions)
L'enumerazione ParallelMergeOptions include le opzioni seguenti che specificano, per le forme di query supportate, il modo in cui viene restituito l'output finale della query quando i risultati vengono utilizzati in un thread:
Not BufferedL'opzione NotBuffered fa sì che ogni elemento elaborato venga restituito da ogni thread non appena viene prodotto. Questo comportamento è analogo a "streaming" dell'output. Se l'operatore AsOrdered è presente nella query,
NotBufferedmantiene l'ordine degli elementi di origine. Anche seNotBufferedinizia a produrre risultati non appena sono disponibili, il tempo totale per produrre tutti i risultati potrebbe essere ancora più lungo rispetto all'uso di una delle altre opzioni di unione.Auto BufferedL'opzione AutoBuffered fa sì che la query raccolga gli elementi in un buffer e quindi restituisca periodicamente il contenuto del buffer contemporaneamente al thread che utilizza. Questo comportamento è analogo a quello di produrre i dati di origine in "blocchi" anziché usare il comportamento di "streaming" di
NotBuffered.AutoBufferedpuò richiedere più tempo rispettoNotBuffereda rendere disponibile il primo elemento nel thread che utilizza. Le dimensioni del buffer e il comportamento esatto di resa non sono configurabili e possono variare, a seconda di vari fattori correlati alla query.FullyBufferedL'opzione FullyBuffered fa sì che l'output dell'intera query venga memorizzato nel buffer prima che venga restituito uno degli elementi. Quando si usa questa opzione, l'operazione può richiedere più tempo prima che il primo elemento sia disponibile nel thread di utilizzo, ma i risultati completi potrebbero essere comunque prodotti più velocemente rispetto all'uso delle altre opzioni.
Operatori di query che supportano le opzioni di merge
Nella tabella seguente sono elencati gli operatori che supportano tutte le modalità di opzione di merge, soggette alle restrizioni specificate.
| Operatore | Restrizioni |
|---|---|
| AsEnumerable | Nessuno |
| Cast | Nessuno |
| Concat | Query non ordinate che hanno come origine solo un Array o una Lista. |
| DefaultIfEmpty | Nessuno |
| OfType | Nessuno |
| Reverse | Query non ordinate che hanno come origine solo un Array o una Lista. |
| Select | Nessuno |
| SelectMany | Nessuno |
| Skip | Nessuno |
| Take | Nessuno |
| Where | Nessuno |
Tutti gli altri operatori di query PLINQ potrebbero ignorare le opzioni di unione fornite dall'utente. Alcuni operatori di query, Reverse ad esempio e OrderBy, non possono restituire alcun elemento finché non vengono prodotti e riordinati tutti. Pertanto, quando ParallelMergeOptions viene usato in una query che contiene anche un operatore, ad Reverseesempio , il comportamento di merge non verrà applicato nella query fino a quando tale operatore non ha prodotto i risultati.
La possibilità di alcuni operatori di gestire le opzioni di unione dipende dal tipo della sequenza di origine e dal fatto che l'operatore AsOrdered sia stato usato in precedenza nella query. ForAll è sempre NotBuffered ; restituisce immediatamente i relativi elementi. OrderBy è sempre FullyBuffered; deve ordinare l'intero elenco prima che restituisca.