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

C# 스레드 풀(Thread Pool) 완벽 가이드: 개념부터 실전 활용까지

C#에서 스레드 풀(Thread Pool)은 백그라운드 작업을 효율적으로 처리하기 위해 시스템이 미리 만들어 관리하는 스레드들의 집합입니다. 작업이 필요할 때마다 매번 새로운 스레드를 생성하고 소멸시키면 상당한 오버헤드가 발생하지만, 스레드 풀을 사용하면 이러한 비용을 크게 줄일 수 있습니다.

스레드 풀이란 무엇인가?

스레드 풀은 이름 그대로 '풀(Pool)'처럼 여러 개의 스레드를 담아두고 필요할 때 꺼내 쓰는 방식으로 동작합니다. 작업 요청이 들어오면 풀에 있는 유휴(idle) 스레드가 이를 처리하고, 작업이 완료된 스레드는 소멸되지 않고 대기 큐(queue)로 반환되어 다음 작업에 재사용됩니다.

이러한 재사용 구조 덕분에 스레드 생성·소멸에 드는 비용이 절감되고, 전체 애플리케이션의 성능과 응답성이 향상됩니다. 특히 짧고 반복적인 백그라운드 작업이 많은 환경에서 스레드 풀은 매우 효과적인 선택입니다.

1단계: 네임스페이스 추가

스레드 풀을 사용하려면 먼저 다음 네임스페이스를 코드에 포함해야 합니다.

using System.Threading;

2단계: QueueUserWorkItem으로 작업 등록

스레드 풀에 작업을 맡기려면 ThreadPool 클래스의 QueueUserWorkItem 메서드를 호출합니다. 이 메서드는 실행할 작업을 WaitCallback 델리게이트 형태로 받아 대기 큐에 등록하며, 가용 스레드가 있는 즉시 해당 스레드가 작업을 수행합니다.

ThreadPool.QueueUserWorkItem(new WaitCallback(Run));

여기서 Run은 백그라운드에서 실행될 메서드를 의미합니다. 실제 동작을 확인하기 위한 간단한 예제는 다음과 같습니다.

using System;
using System.Threading;

class Program
{
    static void Main()
    {
        // 스레드 풀에 작업 등록
        ThreadPool.QueueUserWorkItem(new WaitCallback(Run));

        Console.WriteLine("메인 스레드 계속 실행 중...");
        Console.ReadLine();
    }

    static void Run(object state)
    {
        Console.WriteLine("스레드 풀에서 백그라운드 작업 실행");
    }
}

3단계: 반복문을 통한 활용 및 일반 스레드와의 비교

여러 작업을 처리해야 한다면 QueueUserWorkItem 호출을 반복문 안에서 수행하면 됩니다. 이렇게 하면 각 작업이 스레드 풀의 가용 스레드에 순차적으로 분배되어 병렬로 처리됩니다.

for (int i = 0; i < 5; i++)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(Run), i);
}

그렇다면 스레드 풀과 직접 생성한 일반 Thread 객체는 어떤 차이가 있을까요?

  • 생성 비용: 일반 Thread 객체는 생성될 때마다 새 스레드를 만들어 비용이 크지만, 스레드 풀은 기존 스레드를 재사용하므로 오버헤드가 적습니다.
  • 수명 관리: 일반 스레드는 작업 종료 후 개발자가 직접 관리해야 하는 반면, 스레드 풀의 스레드는 작업 완료 후 자동으로 큐로 반환되어 관리 부담이 없습니다.
  • 제어권: 일반 스레드는 우선순위 지정이나 Foreground/Background 설정 등 세밀한 제어가 가능하지만, 스레드 풀은 이런 세부 제어가 제한적입니다.
  • 적합한 용도: 수명이 짧고 빈번하게 발생하는 작업에는 스레드 풀이, 오랫동안 실행되거나 특별한 제어가 필요한 작업에는 일반 스레드가 더 적합합니다.

마무리

C#의 스레드 풀은 System.Threading 네임스페이스와 QueueUserWorkItem 메서드만으로 손쉽게 활용할 수 있는 강력한 도구입니다. 스레드를 재사용하여 리소스 낭비를 막고 성능을 높일 수 있으므로, 백그라운드 작업 처리가 필요하다면 일반 스레드 생성보다 스레드 풀 사용을 우선적으로 고려해 보시기 바랍니다.