PLINQ および TPL のラムダ式Lambda Expressions in PLINQ and TPL

タスク並列ライブラリ (TPL) には、入力パラメーターとしてデリゲートの System.Func<TResult> または System.Action ファミリのいずれかを受け取る多くのメソッドが含まれます。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. これらのデリゲートを使用して、並列ループ、タスク、またはクエリにカスタムのプログラム ロジックを渡します。You use these delegates to pass in your custom program logic to the parallel loop, task or query. TPL と PLINQ のコード例では、ラムダ式を使用して、インライン コード ブロックとしてこれらのデリゲートのインスタンスを作成します。The code examples for TPL as well as PLINQ use lambda expressions to create instances of those delegates as inline code blocks. このトピックでは、Func および Action について簡単に紹介し、タスク並列ライブラリと PLINQ でラムダ式を使用する方法を示します。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.

メモ 一般的なデリゲートの詳細については、「デリゲート」と「デリゲート」を参照してください。Note For more information about delegates in general, see Delegates and Delegates. C# と Visual Basic のラムダ式の詳細については、それぞれ「ラムダ式」と「ラムダ式」を参照してください。For more information about lambda expressions in C# and Visual Basic, see Lambda Expressions and Lambda Expressions.

Func デリゲートFunc Delegate

Func デリゲートは、値を返すメソッドをカプセル化します。A Func delegate encapsulates a method that returns a value. Func シグネチャでは、末尾または最も右の型パラメーターが常に戻り値の型を指定します。In a Func signature, the last or rightmost type parameter always specifies the return type. コンパイラ エラーの一般的な原因の 1 つは、2 つの入力パラメーターを System.Func<T,TResult> に渡そうとしていることです。この型は、実際には 1 つの入力パラメーターのみを受け取ります。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. Framework クラス ライブラリでは、System.Func<TResult>System.Func<T,TResult>System.Func<T1,T2,TResult> から System.Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult> までの 17 バージョンの Func を定義します。The Framework Class Library 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>.

Action デリゲートAction Delegate

System.Action デリゲートは、値を返さない、または void を返すメソッド (Visual Basic では Sub) をカプセル化します。A System.Action delegate encapsulates a method (Sub in Visual Basic) that does not return a value, or returns void. Action 型シグネチャでは、型パラメーターは、入力パラメーターのみを表します。In an Action type signature, the type parameters represent only input parameters. Func のように、Framework クラス ライブラリでは、型パラメーターを持たないバージョンから 16 の型パラメーターを持つバージョンまでの、17 バージョンの Action が定義されています。Like Func, the Framework Class Library defines 17 versions of Action, from a version that has no type parameters up through a version that has 16 type parameters.

Example

Parallel.ForEach<TSource,TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource,ParallelLoopState,TLocal,TLocal>, Action<TLocal>) メソッドの次の例は、ラムダ式を使用して、Func および Action の両方のデリゲートを表す方法を示しています。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

関連項目See also