Como: Criar um Loop de Parallel tem variáveis de segmento locais
Este exemplo mostra como usar variáveis de segmento locais para armazenar e recuperar o estado de cada tarefa separada, é criado por um For loop. Usando dados de segmento local, você pode evitar a sobrecarga da sincronização de um grande número de acessos para o estado compartilhado. Em vez de escrever a um recurso compartilhado em cada iteração, você pode calcular e armazena o valor até que todas as iterações para a tarefa estiverem concluídas. Você pode escrever o resultado final de uma vez ao recurso compartilhado ou passá-lo para outro método.
Exemplo
'How to: Write a Parallel.For Loop That Has Thread-Local Variables
Imports System.Threading
Imports System.Threading.Tasks
Module ForWithThreadLocal
Sub Main()
Dim nums As Integer() = Enumerable.Range(0, 1000000).ToArray()
Dim total As Long = 0
' Use type parameter to make subtotal a Long type. Function will overflow otherwise.
Parallel.For(Of Long)(0, nums.Length, Function() 0, Function(j, [loop], subtotal)
subtotal += nums(j)
Return subtotal
End Function, Function(x) Interlocked.Add(total, x))
Console.WriteLine("The total is {0}", total)
Console.WriteLine("Press any key to exit")
Console.ReadKey()
End Sub
End Module
namespace ThreadLocalFor
{
using System;
using System.Collections.Generic;
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;
// Use type parameter to make subtotal a long, not an int
Parallel.For<long>(0, nums.Length, () => 0, (j, loop, subtotal) =>
{
subtotal += nums[j];
return subtotal;
},
(x) => Interlocked.Add(ref total, x)
);
Console.WriteLine("The total is {0}", total);
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}
}
}
Os dois primeiros parâmetros de cada For método especificar o início e término valores de iteração. Esta sobrecarga do método, o terceiro parâmetro é onde você inicializar o estado de seu local. " Estado local" neste contexto significa uma variável cuja vida útil se estende da antes de ser a primeira iteração do loop no segmento atual, apenas após a última iteração.
O tipo do terceiro parâmetro é um Func<TResult> onde TResult é o tipo da variável que irá armazenar o estado de segmento local. Observe que neste exemplo, uma versão genérica do método é usada e o parâmetro de tipo é longo (Long em Visual Basic) O parâmetro de tipo informa ao compilador o tipo de variável temporária que será usado para armazenar o estado de segmento local. A expressão () => 0 (Function() 0 em Visual Basic) neste exemplo, significa que a variável de segmento local é inicializada para zero. Se o parâmetro de tipo é um tipo de referência ou tipo de valor definido pelo usuário, este Func ficaria assim:
() => new MyClass()
Function() new MyClass()
O quarto parâmetro de tipo é onde você deve definir a lógica de loop. IntelliSense mostra que ele tem um tipo de Func<int, ParallelLoopState, long, long> ou Func(Of Integer, ParallelLoopState, Long, Long). A expressão lambda espera três parâmetros de entrada na mesma ordem correspondente a esses tipos. O último parâmetro de tipo é o tipo de retorno. Nesse caso, o tipo é longo porque esse é o tipo que especificamos na For tipo de parâmetro. Chamamos essa variável subtotal na expressão lambda e o proprietário de retorno. O valor de retorno é usado para inicializar o subtotal em cada iteração subseqüente. Você também pode considerar este último parâmetro simplesmente como um valor que é passado para cada iteração, e em seguida, o localFinally delegar quando a última iteração é concluída.
O quinto parâmetro é onde você define o método que será chamado uma vez, depois de concluíram todas as iterações neste thread. O tipo de parâmetro de entrada novamente corresponde ao parâmetro de tipo de For método e o tipo retornado pela expressão lambda corpo. Neste exemplo, o valor é adicionado a uma variável no escopo de classe em um thread de maneira segura. Usando uma variável de segmento local, podemos ter evitado escrita a essa variável de classe em cada iteração de cada segmento.
Para obter mais informações sobre como usar expressões lambda, consulte Expressões lambda no PLINQ e TPL.
Consulte também
Conceitos
Paralelismo de dados (biblioteca paralela de tarefas)
Programação em paralela a.NET Framework