Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
O exemplo a seguir mostra como escrever um método ForEach que usa variáveis de partição local. Quando um loop ForEach é executado, ele divide sua coleção de código-fonte em várias partições. Cada partição tem sua própria cópia da variável partição-local. Uma variável partição-local é semelhante a uma variável -thread-local, exceto que várias partições podem ser executadas em um único thread.
O código e os parâmetros neste exemplo se assemelham muito ao método For correspondente. Para obter mais informações, consulte Como escrever um loop Parallel.For com variáveis Thread-Local.
Para usar uma variável partição-local em um loop de ForEach, você deve chamar uma das sobrecargas de método que usa dois parâmetros de tipo. O primeiro parâmetro type, TSource, especifica o tipo do elemento source e o segundo parâmetro type, TLocal, especifica o tipo da variável partition-local.
Exemplo
O exemplo a seguir chama a sobrecarga Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) para calcular a soma de uma matriz de um milhão de elementos. Esta sobrecarga tem quatro parâmetros:
source, que é a fonte de dados. Deve aplicar IEnumerable<T>. A fonte de dados em nosso exemplo é o objeto deIEnumerable<Int32>de um milhão de membros retornado pelo método Enumerable.Range.localInitou a função que inicializa a variável local da partição. Esta função é chamada uma vez para cada partição na qual a operação Parallel.ForEach é executada. Nosso exemplo inicializa a variável partition-local como zero.body, um Func<T1,T2,T3,TResult> que é invocado pelo loop paralelo em cada iteração do loop. A sua assinatura éFunc\<TSource, ParallelLoopState, TLocal, TLocal>. Você fornece o código para o delegado, e o loop passa os parâmetros de entrada, que são:O elemento atual da IEnumerable<T>.
Uma variável ParallelLoopState que você pode usar no código do delegado para examinar o estado do loop.
A variável local da partição.
Seu delegado retorna a variável partição-local, que é então passada para a próxima iteração do loop que é executado nessa partição específica. Cada partição de loop mantém uma instância separada dessa variável.
No exemplo, o delegado adiciona o valor de cada inteiro à variável partição-local, que mantém um total em execução dos valores dos elementos inteiros nessa partição.
localFinally, umAction<TLocal>delegado que o Parallel.ForEach invoca quando as operações de looping em cada partição tenham sido concluídas. O método Parallel.ForEach passa o seuAction<TLocal>delega o valor final da variável partição-local para esta partição de loop e você fornece o código que executa a ação necessária para combinar o resultado dessa partição com os resultados das outras partições. Este delegado pode ser invocado simultaneamente por várias tarefas. Por isso, o exemplo usa o método Interlocked.Add(Int32, Int32) para sincronizar o acesso à variáveltotal. Como o tipo de delegado é um Action<T>, não há valor de retorno.
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Test
{
static void Main()
{
int[] nums = Enumerable.Range(0, 1000000).ToArray();
long total = 0;
// First type parameter is the type of the source elements
// Second type parameter is the type of the thread-local variable (partition subtotal)
Parallel.ForEach<int, long>(
nums, // source collection
() => 0, // method to initialize the local variable
(j, loop, subtotal) => // method invoked by the loop on each iteration
{
subtotal += j; //modify local variable
return subtotal; // value to be passed to next iteration
},
// Method to be executed when each partition has completed.
// finalResult is the final value of subtotal for a particular partition.
(finalResult) => Interlocked.Add(ref total, finalResult));
Console.WriteLine($"The total from Parallel.ForEach is {total:N0}");
}
}
// The example displays the following output:
// The total from Parallel.ForEach is 499,999,500,000
' How to: Write a Parallel.ForEach Loop That Has Thread-Local Variables
Imports System.Threading
Imports System.Threading.Tasks
Module ForEachThreadLocal
Sub Main()
Dim nums() As Integer = Enumerable.Range(0, 1000000).ToArray()
Dim total As Long = 0
' First type parameter is the type of the source elements
' Second type parameter is the type of the thread-local variable (partition subtotal)
Parallel.ForEach(Of Integer, Long)(nums, Function() 0,
Function(elem, loopState, subtotal)
subtotal += elem
Return subtotal
End Function,
Sub(finalResult)
Interlocked.Add(total, finalResult)
End Sub)
Console.WriteLine("The result of Parallel.ForEach is {0:N0}", total)
End Sub
End Module
' The example displays the following output:
' The result of Parallel.ForEach is 499,999,500,000