Partilhar via


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

Biblioteca paralela de tarefas

Expressões lambda no PLINQ e TPL