다음을 통해 공유


방법: 스레드 로컬 변수를 사용하는 Parallel.ForEach 루프 작성

다음 예제에서는 스레드 로컬 변수를 사용하는 ForEach 메서드의 작성 방법을 보여 줍니다. ForEach 루프가 실행되면 소스 컬렉션이 여러 개의 파티션으로 분할됩니다. 각 파티션은 "스레드 로컬" 변수의 고유한 복사본을 갖게 됩니다. 경우에 따라서는 두 파티션이 동일한 스레드에서 실행될 수도 있다는 점을 고려하면 "스레드 로컬"이라는 용어가 약간은 부정확한 의미로 사용되고 있음을 참고하십시오.

이 예제의 코드 및 매개 변수는 상응하는 For 메서드와 매우 유사합니다. 자세한 내용은 방법: 스레드 로컬 변수를 사용하는 Parallel.For 루프 작성을 참조하십시오.

예제

스레드 로컬 변수를 ForEach 루프에서 사용하려면 두 개의 type 매개 변수를 받아들이는 버전의 메서드를 사용해야 합니다. 첫 번째 매개 변수는 소스 요소의 형식을 지정하고, 두 번째 매개 변수는 스레드 로컬 변수의 형식을 지정합니다.

첫 번째 입력 매개 변수는 데이터 소스이고, 두 번째 입력 매개 변수는 스레드 로컬 변수를 초기화할 함수입니다. 세 번째 입력 매개 변수는 병렬 루프가 각 반복에서 호출하는 Func<T1, T2, T3, TResult>입니다. 대리자 코드는 사용자가 제공하고 루프는 입력 매개 변수를 전달합니다. 입력 매개 변수는 루프 상태 및 스레드 로컬 변수를 검사할 수 있게 하는 ParallelLoopState 변수이며 현재 요소입니다. 스레드 로컬 변수를 반환하면 메서드에서 해당 변수를 이 파티션의 다음 반복에 전달합니다. 이 변수는 모든 루프 파티션에서 고유합니다.

ForEach 메서드의 마지막 입력 매개 변수는 모든 루프가 완료될 때 이 메서드에서 호출할 Action<T> 대리자입니다. 이 메서드는 스레드 로컬 변수의 최종 값을 이 스레드 또는 루프 파티션에 제공합니다. 최종 값을 캡처하고 이 파티션의 결과를 다른 파티션의 결과와 결합하는 데 필요한 모든 작업을 수행하는 코드는 사용자가 제공합니다. 대리자 형식은 Action<T>이기 때문에 반환 값은 없습니다.

' How to: Write a Parallel.ForEach Loop That Has Thread-Local Variables

Imports System.Threading
Imports System.Threading.Tasks

Module ForEachThreadLocal
    Sub Main()

        Dim nums() As Integer = Enumerable.Range(0, 1000000).ToArray()
        Dim total As Long = 0

        ' First type paramemter is the type of the source elements
        ' Second type parameter is the type of the local data (subtotal)
        Parallel.ForEach(Of Integer, Long)(nums, Function() 0,
                                           Function(elem, loopState, subtotal)
                                               subtotal += nums(elem)
                                               Return subtotal
                                           End Function,
                                            Sub(finalResult)
                                                Interlocked.Add(total, finalResult)
                                            End Sub)

        Console.WriteLine("The result of Parallel.ForEach is {0}", total)
        Console.WriteLine("Press any key to exit.")
        Console.ReadKey()
    End Sub
End Module
namespace ThreadLocalForEach
{
    using System;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;


    class Test
    {

        static void Main()
        {
            int[] nums = Enumerable.Range(0, 1000000).ToArray();
            long total = 0;

            // First type parameter is the type of the source elements
            // Second type parameter is the type of the local data (subtotal)
            Parallel.ForEach<int, long>(nums, // source collection
                                        () => 0, // method to initialize the local variable
                                        (j, loop, subtotal) => // method invoked by the loop on each iteration
                                        {
                                            subtotal += nums[j]; //modify local variable
                                            return subtotal; // value to be passed to next iteration
                                        },
                // Method to be executed when all loops have completed.
                // finalResult is the final value of subtotal. supplied by the ForEach method.
                                        (finalResult) => Interlocked.Add(ref total, finalResult)
                                        );

            Console.WriteLine("The total from Parallel.ForEach is {0}", total);
            Console.WriteLine("Press any key to exit");
            Console.ReadKey();
        }
    }
}

참고 항목

작업

방법: 스레드 로컬 변수를 사용하는 Parallel.For 루프 작성

개념

데이터 병렬 처리(작업 병렬 라이브러리)

PLINQ 및 TPL의 람다 식