Expressões lambda no PLINQ e TPL

A tarefa paralela TPL (biblioteca) contém muitos métodos de tomar uma da System.Func<TResult> ou System.Action família de delegados como parâmetros de entrada. Você pode usar esses delegados para passar na lógica do seu programa personalizado para o loop paralelo, a tarefa ou a consulta. Os exemplos de código para TPL, bem como PLINQ usam expressões lambda para criar instâncias desses representantes como blocos de código embutido. Este tópico fornece uma breve introdução ao Func e ação e mostra como usar as expressões lambda na biblioteca paralela de tarefas e PLINQ.

Notapara obter mais informações sobre delegados em geral, consulte Representantes (guia de programação C#) e Delegados (Visual Basic). Para obter mais informações sobre as expressões lambda em C# e Visual Basic, consulte Expressões lambda (guia de programação TRANSLATION FROM VPE FOR CSHARP) e Expressões Lambda (Visual Basic).

Func delegado

A Func delegate encapsula um método que retorna um valor. Uma assinatura Func, o parâmetro de tipo do último ou para a direita sempre Especifica o tipo de retorno. Uma causa comum de erros do compilador é tentar passar dois parâmetros de entrada para um System.Func<T, TResult>; Na verdade, esse tipo leva apenas um parâmetro de entrada. A biblioteca de classes do Framework define 17 versões Func: System.Func<TResult>, System.Func<T, TResult>, System.Func<T1, T2, TResult>, and so on up through System.Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>.

Delegado de ação

A System.Action delegate encapsula um método (Sub em Visual Basic) que não retorna um valor, ou retorna void. Uma assinatura de tipo de ação, os parâmetros de tipo representam apenas os parâmetros de entrada. Como Func, a biblioteca de classes do Framework define 17 versões de ação, a partir de uma versão que não tem nenhum parâmetro de tipo até por meio de uma versão de 16 parâmetros de tipo.

Exemplo

O exemplo a seguir para o Parallel.ForEach<TSource, TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource, ParallelLoopState, TLocal, TLocal>, Action<TLocal>) método mostra como express delegados Func e a ação usando lambda expressões.

Imports System.Threading
Imports System.Threading.Tasks
Module ForEachDemo

    ' Demonstrated features:
    '   Parallel.ForEach()
    '   Thread-local state
    ' Expected results:
    '   This example sums up the elements of an int[] in parallel.
    '   Each thread maintains a local sum. When a thread is initialized, that local sum is set to 0.
    '   On every iteration the current element is added to the local sum.
    '   When a thread is done, it safely adds its local sum to the global sum.
    '   After the loop is complete, the global sum is printed out.
    ' Documentation:
    '   https://msdn.microsoft.com/en-us/library/dd990270(VS.100).aspx
    Private Sub ForEachDemo()
        ' The sum of these elements is 40.
        Dim input As Integer() = {4, 1, 6, 2, 9, 5, _
        10, 3}
        Dim sum As Integer = 0

        Try
            ' source collection
            Parallel.ForEach(input,
                             Function()
                                 ' thread local initializer
                                 Return 0
                             End Function,
                             Function(n, loopState, localSum)
                                 ' body
                                 localSum += n
                                 Console.WriteLine("Thread={0}, n={1}, localSum={2}", Thread.CurrentThread.ManagedThreadId, n, localSum)
                                 Return localSum
                             End Function,
                             Sub(localSum)
                                 ' thread local aggregator
                                 Interlocked.Add(sum, localSum)
                             End Sub)

            Console.WriteLine(vbLf & "Sum={0}", sum)
        Catch e As AggregateException
            ' No exception is expected in this example, but if one is still thrown from a task,
            ' it will be wrapped in AggregateException and propagated to the main thread.
            Console.WriteLine("Parallel.ForEach has thrown an exception. THIS WAS NOT EXPECTED." & vbLf & "{0}", e)
        End Try
    End Sub


End Module
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

class ForEachWithThreadLocal
{
    // Demonstrated features:
    //      Parallel.ForEach()
    //      Thread-local state
    // Expected results:
    //      This example sums up the elements of an int[] in parallel.
    //      Each thread maintains a local sum. When a thread is initialized, that local sum is set to 0.
    //      On every iteration the current element is added to the local sum.
    //      When a thread is done, it safely adds its local sum to the global sum.
    //      After the loop is complete, the global sum is printed out.
    // Documentation:
    //      https://msdn.microsoft.com/en-us/library/dd990270(VS.100).aspx
    static void Main()
    {
        // The sum of these elements is 40.
        int[] input = { 4, 1, 6, 2, 9, 5, 10, 3 };
        int sum = 0;

        try
        {
            Parallel.ForEach(
                    input,                          // source collection
                    () => 0,                         // thread local initializer
                    (n, loopState, localSum) =>      // body
                    {
                        localSum += n;
                        Console.WriteLine("Thread={0}, n={1}, localSum={2}", Thread.CurrentThread.ManagedThreadId, n, localSum);
                        return localSum;
                    },
                    (localSum) => Interlocked.Add(ref sum, localSum)                 // thread local aggregator
                );

            Console.WriteLine("\nSum={0}", sum);
        }
        // No exception is expected in this example, but if one is still thrown from a task,
        // it will be wrapped in AggregateException and propagated to the main thread.
        catch (AggregateException e)
        {
            Console.WriteLine("Parallel.ForEach has thrown an exception. THIS WAS NOT EXPECTED.\n{0}", e);
        }
    }

}

Consulte também

Conceitos

Programação em paralela a.NET Framework