Výrazy lambda v PLINQ a TPL

Knihovna TPL (Task Parallel Library) obsahuje mnoho metod, které jako vstupní parametry přebírají jeden z System.Func<TResult> delegátů nebo System.Action řadu delegátů. Pomocí těchto delegátů předáte logiku vlastního programu paralelní smyčce, úloze nebo dotazu. Příklady kódu pro TPL a PLINQ používají výrazy lambda k vytvoření instancí těchto delegátů jako vložených bloků kódu. Toto téma obsahuje stručný úvod k func a action a ukazuje, jak používat výrazy lambda v Knihovně paralelních úloh a PLINQ.

Poznámka:

Další informace o delegátech obecně naleznete v tématu Delegáti a Delegáti. Další informace o výrazech lambda v jazyce C# a Visual Basic najdete v tématu Výrazy lambda a výrazy lambda.

Func Delegate

Func Delegát zapouzdřuje metodu, která vrací hodnotu. Func V podpisu, poslední nebo úplně vpravo, typ parametru vždy určuje návratový typ. Jednou z běžných příčin chyb kompilátoru je pokus o předání dvou vstupních parametrů do a System.Func<T,TResult>ve skutečnosti tento typ přebírá pouze jeden vstupní parametr. .NET definuje 17 verzí Func: System.Func<TResult>, System.Func<T,TResult>, System.Func<T1,T2,TResult>a tak dále až System.Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult>.

Delegát akce

System.Action Delegát zapouzdřuje metodu (Sub v jazyce Visual Basic), která nevrací hodnotu. Action V podpisu typu představují parametry typu pouze vstupní parametry. Podobně jako Funcrozhraní .NET definuje 17 verzí Actionz verze, která nemá parametry typu až do verze, která má 16 parametrů typu.

Příklad

Následující příklad pro metodu Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) ukazuje, jak vyjádřit func i action delegáty pomocí výrazů lambda.

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

Viz také