Share via


PLINQ 및 TPL의 람다 식

TPL(작업 병렬 라이브러리)에는 입력 매개 변수로 대리자의 System.Func<TResult> 또는 System.Action 패밀리 중 하나를 사용하는 여러 메서드가 들어 있습니다. 이러한 대리자를 사용하여 병렬 루프, 작업 또는 쿼리에 사용자 지정 프로그램 논리를 전달합니다. TPL과 PLINQ를 위한 코드 예제에서는 람다 식을 사용하여 이러한 대리자의 인스턴스를 인라인 코드 블록으로 만듭니다. 이 항목에서는 Func 및 Action에 대해 간략히 소개하고 작업 병렬 라이브러리 및 PLINQ에서 람다 식을 사용하는 방법을 보여 줍니다.

참고   일반적인 대리자에 대한 자세한 내용은 대리자(C# 프로그래밍 가이드)대리자(Visual Basic)를 참조하십시오. C# 및 Visual Basic의 람다 식에 대한 자세한 내용은 람다 식(C# 프로그래밍 가이드)람다 식(Visual Basic)을 참조하십시오.

Func 대리자

Func 대리자는 값을 반환하는 메서드를 캡슐화합니다. Func 시그니처에서 마지막 또는 맨 오른쪽의 형식 매개 변수는 항상 반환 형식을 지정합니다. 컴파일러 오류가 발생하는 일반적인 원인 중 하나는 사실 System.Func<T, TResult>는 하나의 입력 매개 변수만 사용하는데 여기에 두 개의 입력 매개 변수를 전달하려고 하기 때문입니다. .NET Framework 클래스 라이브러리에는 17개 버전의 Func, 즉 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>까지의 버전이 정의되어 있습니다.

Action 대리자

System.Action 대리자는 값을 반환하지 않거나 void를 반환하는 메서드(Visual Basic의 경우 Sub)를 캡슐화합니다. Action 형식의 시그니처에서 형식 매개 변수는 입력 매개 변수만을 나타냅니다. Func의 경우와 마찬가지로 .NET Framework 클래스 라이브러리에는 형식 매개 변수가 없는 버전부터 16개의 형식 매개 변수가 있는 버전까지 모두 17개 버전의 Action이 정의되어 있습니다.

예제

Parallel.ForEach<TSource, TLocal>(IEnumerable<TSource>, Func<TLocal>, Func<TSource, ParallelLoopState, TLocal, TLocal>, Action<TLocal>) 메서드에 대한 다음 예제에서는 람다 식을 사용하여 Func 및 Action 대리자를 표현하는 방법을 보여 줍니다.

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

}

참고 항목

개념

.NET Framework의 병렬 프로그래밍