Computer >> 컴퓨터 >  >> 프로그래밍 >> C#

C# 스레드 풀(Thread Pool) 만들기 – QueueUserWorkItem 활용법과 예제

C# 스레드 풀(Thread Pool)이란?

스레드 풀은 스레드를 반복적으로 생성하고 소멸시키는 오버헤드를 줄이기 위해, 미리 만들어 둔 스레드들을 재사용하면서 여러 작업을 동시에 처리하는 기법입니다. .NET에서는 ThreadPool 클래스를 통해 시스템이 관리하는 스레드 풀을 손쉽게 활용할 수 있습니다.

스레드 풀에 작업을 맡기려면 실행할 메서드를 두 개 이상 정의한 뒤, 각 메서드를 실행 대기열(큐)에 등록하면 됩니다. 먼저 다음과 같이 메서드를 하나 작성해 보겠습니다.

public void one(object o) {
    for (int i = 0; i <= 3; i++) {
        Console.WriteLine("One executed");
    }
}

같은 방식으로 나머지 메서드들도 정의한 후, ThreadPool.QueueUserWorkItem 메서드를 사용하여 실행할 메서드들을 큐에 등록합니다. 이때 등록하는 메서드는 WaitCallback 델리게이트, 즉 object 타입 매개변수 하나를 받고 반환값이 없는(void) 형태와 일치해야 합니다.

Demo d = new Demo();
for (int i = 0; i < 3; i++) {
    ThreadPool.QueueUserWorkItem(new WaitCallback(d.one));
    ThreadPool.QueueUserWorkItem(new WaitCallback(d.two));
    ThreadPool.QueueUserWorkItem(new WaitCallback(d.three));
}

위 루프는 3번 반복되므로 one, two, three 메서드가 각각 3회씩, 총 9개의 작업이 스레드 풀의 대기열에 추가됩니다. 스레드 풀은 가용한 스레드에 작업을 분배하며, 어떤 스레드가 어떤 작업을 먼저 처리할지는 실행 시점의 상황에 따라 결정됩니다.

전체 예제 코드

다음 C# 코드를 실행하면 스레드 풀이 실제로 동작하는 모습을 확인할 수 있습니다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
class Demo {
    public void one(object o) {
        for (int i = 0; i <= 3; i++) {
            Console.WriteLine("One executed");
        }
    }
    public void two(object o) {
        for (int i = 0; i <= 3; i++) {
            Console.WriteLine("Two executed");
        }
    }
    public void three(object o) {
        for (int i = 0; i <= 3; i++) {
            Console.WriteLine("Three executed");
        }
    }
    static void Main() {
        Demo d = new Demo();
        for (int i = 0; i < 3; i++) {
            ThreadPool.QueueUserWorkItem(new WaitCallback(d.one));
            ThreadPool.QueueUserWorkItem(new WaitCallback(d.two));
            ThreadPool.QueueUserWorkItem(new WaitCallback(d.three));
        }
        Console.Read();
    }
}

출력 결과

실행 결과는 실행할 때마다 달라질 수 있습니다. 여러 스레드가 동시에 작업을 수행하기 때문에 출력 순서는 보장되지 않으며, 아래 결과에서도 "Two executed", "One executed", "Three executed"가 서로 뒤섞여 출력되는 것을 확인할 수 있습니다.

Two executed
Two executed
Two executed
Two executed
Two executed
Two executed
Two executed
One executed
One executed
One executed
One executed
One executed
Two executed
Two executed
Three executed
Three executed
Two executed
One executed
Three executed
Two executed
Three executed
One executed
One executed
One executed

핵심 정리

  • ThreadPool.QueueUserWorkItem(WaitCallback): 실행할 메서드를 스레드 풀의 대기열에 등록하는 메서드입니다.
  • WaitCallback: object 매개변수 하나를 받고 반환값이 없는 메서드를 참조하는 델리게이트입니다.
  • 스레드 풀의 스레드는 백그라운드 스레드로 동작하며, 작업의 시작 순서나 완료 순서는 보장되지 않습니다.
  • Main 메서드 마지막의 Console.Read()는 프로그램이 즉시 종료되어 백그라운드 작업이 끊기지 않도록 입력을 대기하는 역할을 합니다.