Freigeben über


Lambda-Ausdrücke in PLINQ und TPL

Die Task Parallel Library (TPL) enthält viele Methoden, die einen Delegaten aus der System.Func<TResult>- oder System.Action-Gruppe als Eingabeparameter verwenden. Sie verwenden diese Delegaten zur Übergabe der benutzerdefinierten Programmlogik an die parallele Schleife, Aufgabe oder Abfrage. In den Codebeispielen für TPL und PLINQ werden Lambda-Ausdrücke verwendet, um Instanzen dieser Delegaten als Inline-Codeblöcke zu erstellen. Dieses Thema enthält eine kurze Einführung in Func und Action und zeigt Ihnen, wie Sie Lambda-Ausdrücke in der Task Parallel Library und PLINQ verwenden.

Hinweis

Weitere Informationen zu Stellvertretungen im Allgemeinen finden Sie unter "Stellvertretungen und Stellvertretungen". Weitere Informationen zu Lambda-Ausdrücken in C# und Visual Basic finden Sie unter Lambda-Ausdrücke und Lambda-Ausdrücke.

Func-Delegat

Ein Func Delegat kapselt eine Methode, die einen Wert zurückgibt. In einer Func Signatur gibt der letzte oder ganz rechts stehende Typparameter immer den Rückgabetyp an. Eine häufige Ursache für Compilerfehler ist das Übergeben von zwei Eingabeparametern an einen System.Func<T,TResult>; tatsächlich verwendet dieser Typ nur einen Eingabeparameter. .NET definiert 17 Versionen von Func: System.Func<TResult>, System.Func<T,TResult>, , System.Func<T1,T2,TResult>usw. durch System.Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult>.

Aktionsdelegat

Ein System.Action Delegat kapselt eine Methode (Sub in Visual Basic), die keinen Wert zurückgibt. In einer Action Typsignatur stellen die Typparameter nur Eingabeparameter dar. Wie Func. NET definiert 17 Versionen von Action, von einer Version, die keine Typparameter bis zu einer Version mit 16 Typparametern enthält.

Beispiel

Im folgenden Beispiel für die Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) Methode wird gezeigt, wie Sie func- und Action-Delegaten mithilfe von Lambda-Ausdrücken ausdrücken.

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

Siehe auch