Como: Criar um Loop de Parallel tem variáveis de segmento locais

O exemplo a seguir mostra como gravar um ForEach método que usa variáveis de segmento local. Quando um ForEach o loop é executado, ele divide a sua coleção de origem em várias partições. Cada partição terá sua própria cópia de "thread-local" variável. (O termo "thread-local" é um pouco impreciso aqui, porque em alguns casos, duas partições pode ser executado no mesmo thread.)

O código e os parâmetros neste exemplo parecido com o correspondente For método. Para obter mais informações, consulte Como: Criar um Loop de Parallel tem variáveis de segmento locais.

Exemplo

Para usar uma variável de segmento locais em um ForEach loop, você deve usar a versão do método que assume dois type parâmetros. O primeiro parâmetro especifica o tipo de elemento de origem e o segundo parâmetro especifica o tipo de variável de segmento local.

O primeiro parâmetro de entrada é a fonte de dados e o segundo é a função que irá inicializar a variável de segmento local. O terceiro parâmetro de entrada é um Func<T1, T2, T3, TResult> que é invocado pelo loop paralelo em cada iteração. Você fornecer o código para o representante e o loop passa os parâmetros de entrada. Os parâmetros de entrada são o elemento atual, um ParallelLoopState variável que permite que você examine o estado de loop e a variável de segmento local. Retornar a variável de segmento local e o método e passa para a próxima iteração nesta partição. Essa variável é distinto em todas as partições de loop.

O último parâmetro de entrada do ForEach método é o Action<T> representante invocará o método quando tem concluído a todos os loops. O método fornece o valor final da variável local de segmento do segmento (ou partição de loop) e fornecer o código que captura o valor final e executa qualquer ação é necessária para combinar o resultado desta partição com os resultados de outras partições. Porque o tipo de delegado é um Action<T>, não há nenhum valor de retorno.

' 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 paramemter is the type of the source elements
        ' Second type parameter is the type of the local data (subtotal)
        Parallel.ForEach(Of Integer, Long)(nums, Function() 0,
                                           Function(elem, loopState, subtotal)
                                               subtotal += nums(elem)
                                               Return subtotal
                                           End Function,
                                            Sub(finalResult)
                                                Interlocked.Add(total, finalResult)
                                            End Sub)

        Console.WriteLine("The result of Parallel.ForEach is {0}", total)
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub
End Module
namespace ThreadLocalForEach
{
    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 local data (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 += nums[j]; //modify local variable
                                            return subtotal; // value to be passed to next iteration
                                        },
                // Method to be executed when all loops have completed.
                // finalResult is the final value of subtotal. supplied by the ForEach method.
                                        (finalResult) => Interlocked.Add(ref total, finalResult)
                                        );

            Console.WriteLine("The total from Parallel.ForEach is {0}", total);
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

Consulte também

Tarefas

Como: Criar um Loop de Parallel tem variáveis de segmento locais

Conceitos

Paralelismo de dados (biblioteca paralela de tarefas)

Expressões lambda no PLINQ e TPL