Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
No PLINQ, a meta é maximizar o desempenho e manter a correção. Uma consulta deve ser executada o mais rápido possível, mas ainda produzir os resultados corretos. Em alguns casos, a correção requer que a ordem da sequência de origem seja preservada; no entanto, a ordenação pode ser computacionalmente cara. Portanto, por padrão, o PLINQ não preserva a ordem da sequência de origem. Nesse sentido, o PLINQ é semelhante ao LINQ to SQL, mas é diferente do LINQ to Objetos, que preserva a ordenação.
Para substituir o comportamento padrão, você pode ativar a preservação da ordem usando o AsOrdered operador na sequência de origem. Em seguida, você pode desativar a preservação da ordem posteriormente na consulta usando o AsUnordered método. Com ambos os métodos, a consulta é processada com base na heurística que determina se a consulta deve ser executada como paralela ou sequencial. Para obter mais informações, consulte Noções básicas sobre a aceleração no PLINQ.
O exemplo a seguir mostra uma consulta paralela não ordenada que filtra todos os elementos que correspondem a uma condição, sem tentar ordenar os resultados de forma alguma.
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)
Essa consulta não necessariamente produz as primeiras 1000 cidades na sequência de origem que atendem à condição, mas sim alguns conjuntos de 1000 cidades que atendem à condição. Os operadores de consulta PLINQ particionam a sequência de origem em várias subsequências que são processadas como tarefas simultâneas. Se a preservação da ordem não for especificada, os resultados de cada partição serão passados para o próximo estágio do processamento da consulta em uma ordem arbitrária. Além disso, uma partição pode produzir um subconjunto de seus resultados antes de continuar processando os elementos restantes. A ordem resultante pode ser diferente a cada vez. Seu aplicativo não pode controlar isso porque depende de como o sistema operacional agenda os threads.
O exemplo a seguir substitui o comportamento padrão usando o AsOrdered operador na sequência de origem. Isso garante que o Take método retorne as primeiras 1000 cidades na sequência de origem que atendem à condição.
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)
No entanto, essa consulta provavelmente não é executada tão rápido quanto a versão não ordenada porque deve acompanhar a ordenação original em todas as partições e, em tempo de mesclagem, garantir que a ordenação seja consistente. Portanto, recomendamos que você use AsOrdered somente quando for necessário e somente para as partes da consulta que exigem isso. Quando a preservação da ordem não for mais necessária, use AsUnordered para desativá-la. O exemplo a seguir consegue isso compondo duas consultas.
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
Observe que o PLINQ preserva a ordenação de uma sequência produzida por operadores que impõem ordem para o restante da consulta. Em outras palavras, operadores como OrderBy e ThenBy são tratados como se fossem seguidos por uma chamada para AsOrdered.
Operadores de consulta e ordenação
Os operadores de consulta a seguir apresentam a preservação da ordem em todas as demais operações de uma consulta ou até que AsUnordered seja chamado:
Os seguintes operadores de consulta PLINQ podem, em alguns casos, exigir sequências de origem ordenadas para produzir resultados corretos:
Alguns operadores de consulta PLINQ se comportam de forma diferente, dependendo se a sequência de origem é ordenada ou não ordenada. A tabela a seguir lista esses operadores.
Operador | Resultado quando a sequência de origem é ordenada | Resultado quando a sequência de origem é desordenada |
---|---|---|
Aggregate | Saída não determinística para operações não determinísticas ou não comunicativas | Saída não determinística para operações não determinísticas ou não comunicativas |
All | Não aplicável | Não aplicável |
Any | Não aplicável | Não aplicável |
AsEnumerable | Não aplicável | Não aplicável |
Average | Saída não determinística para operações não determinísticas ou não comunicativas | Saída não determinística para operações não determinísticas ou não comunicativas |
Cast | Resultados ordenados | Resultados não ordenados |
Concat | Resultados ordenados | Resultados não ordenados |
Count | Não aplicável | Não aplicável |
DefaultIfEmpty | Não aplicável | Não aplicável |
Distinct | Resultados ordenados | Resultados não ordenados |
ElementAt | Retornar elemento especificado | Elemento arbitrário |
ElementAtOrDefault | Retornar elemento especificado | Elemento arbitrário |
Except | Resultados não ordenados | Resultados não ordenados |
First | Retornar elemento especificado | Elemento arbitrário |
FirstOrDefault | Retornar elemento especificado | Elemento arbitrário |
ForAll | Executa de forma não determinística em paralelo | Executa de forma não determinística em paralelo |
GroupBy | Resultados ordenados | Resultados não ordenados |
GroupJoin | Resultados ordenados | Resultados não ordenados |
Intersect | Resultados ordenados | Resultados não ordenados |
Join | Resultados ordenados | Resultados não ordenados |
Last | Retornar elemento especificado | Elemento arbitrário |
LastOrDefault | Retornar elemento especificado | Elemento arbitrário |
LongCount | Não aplicável | Não aplicável |
Min | Não aplicável | Não aplicável |
OrderBy | Reordena a sequência | Inicia nova seção ordenada |
OrderByDescending | Reordena a sequência | Inicia nova seção ordenada |
Range | Não aplicável (o mesmo padrão que AsParallel ) | Não aplicável |
Repeat | Não aplicável (o mesmo padrão que AsParallel) | Não aplicável |
Reverse | Inverte | Não faz nada |
Select | Resultados ordenados | Resultados não ordenados |
Select (indexado) | Resultados ordenados | Resultados não ordenados. |
SelectMany | Resultados ordenados. | Resultados não ordenados |
SelectMany (indexado) | Resultados ordenados. | Resultados não ordenados. |
SequenceEqual | Comparação ordenada | Comparação não ordenada |
Single | Não aplicável | Não aplicável |
SingleOrDefault | Não aplicável | Não aplicável |
Skip | Ignora os primeiros n elementos | Ignora quaisquer n elementos |
SkipWhile | Resultados ordenados. | Não determinístico. Executa SkipWhile na ordem arbitrária atual |
Sum | Saída não determinística para operações não determinísticas ou não comunicativas | Saída não determinística para operações não determinísticas ou não comunicativas |
Take | Usa os primeiros n elementos |
Usa quaisquer n elementos |
TakeWhile | Resultados ordenados | Não determinístico. Executa TakeWhile na ordem arbitrária atual |
ThenBy | Suplementos OrderBy |
Suplementos OrderBy |
ThenByDescending | Suplementos OrderBy |
Suplementos OrderBy |
ToArray | Resultados ordenados | Resultados não ordenados |
ToDictionary | Não aplicável | Não aplicável |
ToList | Resultados ordenados | Resultados não ordenados |
ToLookup | Resultados ordenados | Resultados não ordenados |
Union | Resultados ordenados | Resultados não ordenados |
Where | Resultados ordenados | Resultados não ordenados |
Where (indexado) | Resultados ordenados | Resultados não ordenados |
Zip | Resultados ordenados | Resultados não ordenados |
Resultados não ordenados não são reordenados; eles simplesmente não têm nenhum critério especial de ordenação aplicado a eles. Em alguns casos, uma consulta não ordenada pode manter a ordenação da sequência de origem. Para consultas que usam o operador Select indexado, o PLINQ garante que os elementos de saída serão lançados na ordem do aumento dos índices, mas não garante quais índices serão atribuídos a quais elementos.