이 클래스는 System.Threading.ThreadPool 시스템에서 관리하는 작업자 스레드 풀을 애플리케이션에 제공하여 스레드 관리가 아닌 애플리케이션 작업에 집중할 수 있도록 합니다. 백그라운드 처리가 필요한 짧은 작업이 있는 경우 관리되는 스레드 풀은 여러 스레드를 쉽게 활용할 수 있는 방법입니다. 프레임워크 4 이상에서는 스레드 풀 스레드에서 비동기 작업을 수행하는 Task 및 Task<TResult> 객체를 생성할 수 있으므로 스레드 풀 사용이 훨씬 더 쉬워졌습니다.
.NET은 TPL(작업 병렬 라이브러리) 작업, 비동기 I/O 완료, 타이머 콜백, 등록된 대기 작업, 대리자를 사용하는 비동기 메서드 호출 및 System.Net 소켓 연결을 비롯한 여러 용도로 스레드 풀 스레드를 사용합니다.
스레드 풀 특성
스레드 풀 스레드는 백그라운드 스레드입니다. 각 스레드는 기본 스택 크기를 사용하고, 기본 우선 순위에서 실행되며, 다중 스레드 아파트에 있습니다. 스레드 풀의 스레드가 작업을 완료하면 대기 중인 스레드의 큐로 반환됩니다. 이 순간부터 다시 사용할 수 있습니다. 이 재사용을 통해 애플리케이션은 각 작업에 대해 새 스레드를 만드는 비용을 방지할 수 있습니다.
프로세스당 하나의 스레드 풀만 있습니다.
스레드 풀 스레드의 예외
스레드 풀 스레드에서 처리되지 않은 예외는 프로세스를 종료합니다. 이 규칙에는 다음 세 가지 예외가 있습니다.
- System.Threading.ThreadAbortException는 Thread.Abort가 호출되었기 때문에 스레드 풀 스레드에서 throw됩니다.
- 애플리케이션 도메인이 언로드되고 있으므로 스레드 풀의 스레드에서 System.AppDomainUnloadedException가 던져집니다.
- 공용 언어 런타임 또는 호스트 프로세스는 스레드를 종료합니다.
자세한 내용은 관리되는 스레드의 예외를 참조하세요.
스레드 풀 내 스레드의 최대 수
스레드 풀에 큐에 대기할 수 있는 작업의 수는 사용 가능한 메모리에 의해서만 제한됩니다. 그러나 스레드 풀은 프로세스에서 동시에 활성화될 수 있는 스레드 수를 제한합니다. 모든 스레드 풀 스레드가 사용 중인 경우 스레드를 실행할 수 있게 될 때까지 추가 작업 항목이 큐에 대기됩니다. 프로세스에 대한 스레드 풀의 기본 크기는 가상 주소 공간의 크기와 같은 몇 가지 요인에 따라 달라집니다. 프로세스는 메서드를 ThreadPool.GetMaxThreads 호출하여 스레드 수를 확인할 수 있습니다.
ThreadPool.GetMaxThreads 및 ThreadPool.SetMaxThreads 메서드를 사용하여 최대 스레드 수를 제어할 수 있습니다.
비고
공용 언어 런타임을 호스트하는 코드는 메서드를 사용하여 ICorThreadpool::CorSetMaxThreads
크기를 설정할 수 있습니다.
스레드 풀 최소값
스레드 풀은 각 범주에 대해 지정된 최소값에 도달할 때까지 요청 시 새 작업자 스레드 또는 I/O 완료 스레드를 제공합니다. 이 메서드를 ThreadPool.GetMinThreads 사용하여 이러한 최소값을 가져올 수 있습니다.
비고
수요가 낮으면 실제 스레드 풀의 스레드 수가 최소값 이하로 떨어질 수 있습니다.
최소값에 도달하면 스레드 풀이 추가 스레드를 만들거나 일부 작업이 완료될 때까지 기다릴 수 있습니다. 스레드 풀은 처리량을 최적화하기 위해 작업자 스레드를 만들고 삭제하며, 이는 시간 단위당 완료되는 작업 수로 정의됩니다. 스레드가 너무 적으면 사용 가능한 리소스를 최적으로 사용하지 못할 수 있지만 스레드가 너무 많으면 리소스 경합이 증가할 수 있습니다.
주의
이 메서드를 ThreadPool.SetMinThreads 사용하여 최소 유휴 스레드 수를 늘릴 수 있습니다. 그러나 이러한 값을 불필요하게 늘리면 성능 문제가 발생할 수 있습니다. 너무 많은 작업이 동시에 시작되면 모든 작업이 느린 것처럼 보일 수 있습니다. 대부분의 경우 스레드 풀은 스레드를 할당하기 위한 자체 알고리즘을 사용하여 더 나은 성능을 발휘합니다.
스레드 풀 사용
스레드 풀을 사용하는 가장 쉬운 방법은 TPL(작업 병렬 라이브러리)을 사용하는 것입니다. 기본적으로 Task 및 Task<TResult> 같은 TPL 형식은 스레드 풀 스레드를 사용하여 작업을 실행합니다.
관리 코드에서 ThreadPool.QueueUserWorkItem를 호출하거나, 관리되지 않는 코드에서 ICorThreadpool::CorQueueUserWorkItem
를 호출하고, 작업을 수행하는 메서드를 나타내는 대리자 System.Threading.WaitCallback를 전달하여 스레드 풀을 사용할 수도 있습니다.
스레드 풀을 사용하는 또 다른 방법은 ThreadPool.RegisterWaitForSingleObject 메서드를 사용하여 대기 작업과 관련된 작업 항목을 큐에 System.Threading.WaitHandle 대기시키는 것입니다. 신호를 받거나 시간이 초과될 때 대리자가 나타내는 메서드를 호출합니다. 스레드 풀 스레드는 콜백 메서드를 호출하는 데 사용됩니다.
예제를 보려면 참조된 API 페이지를 확인합니다.
보안 검사 건너뛰기
스레드 풀은 또한 ThreadPool.UnsafeQueueUserWorkItem 및 ThreadPool.UnsafeRegisterWaitForSingleObject 메서드를 제공합니다. 호출자의 스택이 큐에 대기 중인 작업을 실행하는 동안 수행된 보안 검사와 무관하다고 확신하는 경우에만 이러한 메서드를 사용합니다. ThreadPool.QueueUserWorkItem와 ThreadPool.RegisterWaitForSingleObject 모두 호출자의 스택을 캡처하여, 스레드가 작업을 실행하기 시작할 때 그 스택을 스레드 풀 스레드의 스택에 병합합니다. 보안 검사가 필요한 경우 전체 스택을 확인해야 합니다. 검사는 안전을 제공하지만 성능 비용도 있습니다.
스레드 풀 스레드를 사용하지 말아야 할 때
스레드 풀 스레드를 사용하는 대신 사용자 고유의 스레드를 만들고 관리하는 것이 적절한 몇 가지 시나리오가 있습니다.
- 포그라운드 스레드가 필요합니다.
- 스레드에 특정 우선 순위가 있어야 합니다.
- 스레드가 오랜 시간 동안 차단되도록 하는 작업이 있습니다. 스레드 풀에는 최대 스레드 수가 있으므로 많은 수의 차단된 스레드 풀 스레드가 작업을 시작하지 못할 수 있습니다.
- 스레드를 단일 스레드 아파트 환경에 배치해야 합니다. 모든 ThreadPool 스레드는 다중 스레드 아파트에 있습니다.
- 스레드와 연결된 안정적인 ID가 있거나 스레드를 작업에 헌정해야 합니다.
참고하십시오
.NET