다음을 통해 공유


방법: 스레드 풀 사용(C# 프로그래밍 가이드)

업데이트: 2007년 11월

스레드 풀은 백그라운드에서 여러 가지 작업을 수행하는 데 사용할 수 있는 스레드의 컬렉션입니다. 자세한 내용은 스레딩 사용(C# 프로그래밍 가이드)을 참조하십시오. 스레드 풀을 사용하면 기본 스레드에서 다른 작업을 비동기적으로 수행할 수 있습니다.

스레드 풀은 대개 서버 응용 프로그램에 사용됩니다. 들어오는 각 요청은 스레드 풀의 스레드에 할당되므로 기본 스레드를 사용할 수 있을 때까지 기다리거나 이후의 요청을 처리하는 데 시간을 지연하지 않고 요청을 비동기적으로 처리할 수 있습니다.

풀에 있는 스레드가 해당 작업을 완료하고 대기 스레드의 큐로 반환되면 여기서 해당 스레드를 다시 사용할 수 있습니다. 이와 같이 스레드를 다시 사용하면 응용 프로그램에서 각 작업에 대해 새 스레드를 만드느라 리소스를 낭비하지 않아도 됩니다.

스레드 풀에는 일반적으로 스레드의 최대 수가 지정되어 있습니다. 모든 스레드에서 작업을 수행 중이면 다른 작업은 사용 가능한 스레드가 생길 때까지 큐에 배치됩니다.

고유한 스레드 풀을 구현할 수도 있지만 ThreadPool 클래스를 통해 .NET Framework에서 제공하는 스레드 풀을 사용하는 것이 더 간편합니다.

다음 예제에서는 .NET Framework 스레드 풀을 사용하여 20과 40 사이의 숫자 10개에 대한 Fibonacci 결과를 계산합니다. 각 Fibonacci 결과는 Fibonacci 클래스로 표현됩니다. 이 클래스는 계산을 수행하는 ThreadPoolCallback이라는 메서드를 제공합니다. 각 Fibonacci 값을 나타내는 개체가 작성되고 ThreadPoolCallback 메서드가 QueueUserWorkItem에 전달되면 이 메서드를 실행하기 위해 풀의 사용 가능한 스레드가 할당됩니다.

각 Fibonacci 개체에는 계산을 위해 어느 정도 임의로 지정되는 값이 할당되고 각 스레드는 프로세서 시간을 할당 받기 위해 경쟁하므로 10개의 결과를 모두 계산하는 데 얼마나 오래 걸릴지 미리 알 수 없습니다. 생성 과정에서 각 Fibonacci 개체가 ManualResetEvent 클래스의 인스턴스에 전달되는 이유는 바로 여기에 있습니다. 각 개체는 해당 계산이 완료되면 제공된 이벤트 개체에 신호를 보내므로 10개의 Fibonacci 개체가 모두 결과를 계산할 때까지 기본 스레드에서 WaitAll을 사용한 실행을 차단할 수 있습니다. 그런 다음 Main 메서드에서 각 Fibonacci 결과를 표시합니다.

예제

using System;
using System.Threading;

public class Fibonacci
{
    public Fibonacci(int n, ManualResetEvent doneEvent)
    {
        _n = n;
        _doneEvent = doneEvent;
    }

    // Wrapper method for use with thread pool.
    public void ThreadPoolCallback(Object threadContext)
    {
        int threadIndex = (int)threadContext;
        Console.WriteLine("thread {0} started...", threadIndex);
        _fibOfN = Calculate(_n);
        Console.WriteLine("thread {0} result calculated...", threadIndex);
        _doneEvent.Set();
    }

    // Recursive method that calculates the Nth Fibonacci number.
    public int Calculate(int n)
    {
        if (n <= 1)
        {
            return n;
        }

        return Calculate(n - 1) + Calculate(n - 2);
    }

    public int N { get { return _n; } }
    private int _n;

    public int FibOfN { get { return _fibOfN; } }
    private int _fibOfN;

    private ManualResetEvent _doneEvent;
}

public class ThreadPoolExample
{
    static void Main()
    {
        const int FibonacciCalculations = 10;

        // One event is used for each Fibonacci object
        ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];
        Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];
        Random r = new Random();

        // Configure and launch threads using ThreadPool:
        Console.WriteLine("launching {0} tasks...", FibonacciCalculations);
        for (int i = 0; i < FibonacciCalculations; i++)
        {
            doneEvents[i] = new ManualResetEvent(false);
            Fibonacci f = new Fibonacci(r.Next(20,40), doneEvents[i]);
            fibArray[i] = f;
            ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);
        }

        // Wait for all threads in pool to calculation...
        WaitHandle.WaitAll(doneEvents);
        Console.WriteLine("All calculations are complete.");

        // Display the results...
        for (int i= 0; i<FibonacciCalculations; i++)
        {
            Fibonacci f = fibArray[i];
            Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);
        }
    }
}

출력은 다음과 같습니다.

launching 10 tasks...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
result calculated...
all calculations complete
Fibonacci(22) = 17711
Fibonacci(25) = 75025
Fibonacci(32) = 2178309
Fibonacci(36) = 14930352
Fibonacci(32) = 2178309
Fibonacci(26) = 121393
Fibonacci(35) = 9227465
Fibonacci(23) = 28657
Fibonacci(39) = 63245986
Fibonacci(22) = 17711

참고 항목

작업

Monitor Synchronization 기술 샘플

Wait Synchronization 기술 샘플

개념

C# 프로그래밍 가이드

Monitor

참조

스레딩(C# 프로그래밍 가이드)

스레딩 사용(C# 프로그래밍 가이드)

Mutex

WaitAll

ManualResetEvent

Set

ThreadPool

QueueUserWorkItem

ManualResetEvent

기타 리소스

HOWTO: Visual C# .NET을 사용하여 다중 스레딩 환경에서 공유 리소스에 대한 액세스 동기화

.NET Framework의 보안