Expressões lambda em PLINQ e TPLLambda Expressions in PLINQ and TPL

A TPL (Biblioteca de Paralelismo de Tarefas) contém vários métodos que usam uma das família de delegados System.Func<TResult> ou System.Action como parâmetros de entrada.The Task Parallel Library (TPL) contains many methods that take one of the System.Func<TResult> or System.Action family of delegates as input parameters. Você pode usar esses delegados para transmitir sua lógica de programa personalizada para o loop paralelo, tarefa ou consulta.You use these delegates to pass in your custom program logic to the parallel loop, task or query. Os exemplos de código para TPL, bem como o PLINQ, usam expressões lambda para criar instâncias desses delegados como blocos de código embutido.The code examples for TPL as well as PLINQ use lambda expressions to create instances of those delegates as inline code blocks. Este tópico fornece uma breve introdução a Func e Action, e mostra como usar expressões lambda no PLINQ e na Biblioteca de paralelismo de tarefas.This topic provides a brief introduction to Func and Action and shows you how to use lambda expressions in the Task Parallel Library and PLINQ.

Observação

Para obter mais informações sobre delegados em geral, consulte delegados e delegados.For more information about delegates in general, see Delegates and Delegates. Para saber mais sobre expressões lambda em C# e em Visual Basic, confira Expressões lambda e Expressões lambda.For more information about lambda expressions in C# and Visual Basic, see Lambda Expressions and Lambda Expressions.

Delegado FuncFunc Delegate

Um delegado Func encapsula um método que retorna um valor.A Func delegate encapsulates a method that returns a value. Em uma Func assinatura, o parâmetro de tipo Last ou mais à direita sempre especifica o tipo de retorno.In a Func signature, the last, or rightmost, type parameter always specifies the return type. Uma causa comum de erros do compilador é tentar passar dois parâmetros de entrada para um System.Func<T,TResult>; na verdade, esse tipo usa somente um parâmetro de entrada.One common cause of compiler errors is to attempt to pass in two input parameters to a System.Func<T,TResult>; in fact this type takes only one input parameter. O .NET define 17 versões de Func : System.Func<TResult> ,, System.Func<T,TResult> System.Func<T1,T2,TResult> e assim por diante System.Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult> ..NET defines 17 versions of 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 ActionAction Delegate

Um System.Action delegado encapsula um método (sub no Visual Basic) que não retorna um valor.A System.Action delegate encapsulates a method (Sub in Visual Basic) that does not return a value. Em uma Action assinatura de tipo, os parâmetros de tipo representam apenas os parâmetros de entrada.In an Action type signature, the type parameters represent only input parameters. Como Func o, o .NET define 17 versões do Action , de uma versão que não tem parâmetros de tipo por meio de uma versão que tem 16 parâmetros de tipo.Like Func, .NET defines 17 versions of Action, from a version that has no type parameters up through a version that has 16 type parameters.

ExemploExample

O exemplo a seguir para o método Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) mostra como expressar delegados Func e Action usando expressões lambda.The following example for the Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) method shows how to express both Func and Action delegates by using lambda expressions.

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:
    //		http://msdn.microsoft.com/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);
        }
    }
}
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:
    '   http://msdn.microsoft.com/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

Consulte tambémSee also