Dela via


Lambda-uttryck i PLINQ och TPL

Biblioteket för parallella uppgifter (TPL) innehåller många metoder som tar en av System.Func<TResult>- eller System.Action-delegatfamiljerna som inmatningsparametrar. Du använder dessa delegeringar för att överföra din anpassade programlogik till den parallella loopen, uppgiften eller frågan. Kodexemplen för TPL och PLINQ använder lambda-uttryck för att skapa instanser av dessa delegater som inline-kodblock. Det här avsnittet innehåller en kort introduktion till Func och Action och visar hur du använder lambda-uttryck i Aktivitetsparallellt bibliotek och PLINQ.

Anmärkning

Mer information om delegater finns i Delegater och Delegater. Mer information om lambda-uttryck i C# och Visual Basic finns i Lambda-uttryck och Lambda-uttryck.

Func-ombud

Ett Func delegat kapslar in en metod som returnerar ett värde. I en Func signatur anger den sista eller den högra parametern alltid returtypen. En vanlig orsak till kompilatorfel är att försöka skicka in två indataparametrar till en System.Func<T,TResult>; I själva verket tar den här typen bara en indataparameter. .NET definierar 17 versioner av Func: System.Func<TResult>, System.Func<T,TResult>, System.Func<T1,T2,TResult>och så vidare upp via System.Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult>.

Åtgärdsdelegat

En System.Action delegering kapslar in en metod (Sub i Visual Basic) som inte returnerar ett värde. I en Action typsignatur representerar typparametrarna endast indataparametrar. Precis som Funcdefinierar .NET 17 versioner av Action, från en version som inte har några typparametrar upp via en version som har 16 typparametrar.

Exempel

Följande exempel för metoden Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) visar hur du uttrycker både Func- och Action-ombud med hjälp av lambda-uttryck.

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={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{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

Se även