C#에서 태스크 병렬 처리(Task Parallelism)는 하나의 작업을 여러 개로 나눈 뒤, 각 작업을 별도의 스레드에 할당해 동시에 처리하는 프로그래밍 기법입니다. 이를 통해 CPU 자원을 효율적으로 활용하고 애플리케이션의 성능을 크게 향상시킬 수 있습니다.
.NET의 병렬 실행 메커니즘
.NET에서는 코드를 병렬로 실행하기 위한 세 가지 주요 메커니즘을 제공합니다.
- Thread: 가장 저수준(low-level)의 스레드 제어 방식
- ThreadPool: 재사용 가능한 스레드 풀을 통해 스레드 생성 비용 절감
- Task: 비동기 및 병렬 작업을 추상화한 고수준 모델
병렬 처리를 구현할 때는 Thread를 직접 다루기보다 Task를 사용하는 것이 권장됩니다. 태스크는 자체적인 OS 스레드를 생성하지 않고, 대신 TaskScheduler가 태스크의 실행을 관리하기 때문입니다. 이 덕분에 시스템 리소스를 더욱 효율적으로 사용할 수 있습니다.
태스크 생성 방법
C#에서 태스크를 생성하고 시작하는 방법은 여러 가지가 있습니다. 상황에 맞는 방식을 선택하면 됩니다.
1. 델리게이트(delegate) 사용
Task tsk = new Task(delegate { PrintMessage(); });
tsk.Start();2. Task.Factory 사용
Task.Factory.StartNew(() => { Console.WriteLine("Welcome!"); });Task.Factory.StartNew는 태스크를 생성함과 동시에 즉시 시작해야 할 때 유용합니다.
3. 람다 식(Lambda) 사용
Task tsk = new Task(() => PrintMessage()); tsk.Start();
4. Task.Run() 사용 — 가장 간단한 방법
태스크를 시작하는 가장 기본적이고 널리 쓰이는 방법은 Task.Run()을 사용하는 것입니다. 아래 예제는 백그라운드에서 반복문을 실행한 후 결과를 출력합니다.
예제 코드
using System;
using System.Threading.Tasks;
public class Example {
public static void Main() {
Task tsk = Task.Run(() => {
int a = 0;
for (a = 0; a <= 1000; a++) {}
Console.WriteLine("{0} loop iterations ends", a);
});
tsk.Wait();
}
}실행 결과
1001 loop iterations ends
위 예제에서 tsk.Wait()는 메인 스레드가 태스크의 완료를 기다리도록 하는 역할을 합니다. 이처럼 Task를 활용하면 복잡한 스레드 관리 없이도 손쉽게 병렬 처리를 구현할 수 있습니다.