C# CancellationToken 연동(연결) 방법 - CreateLinkedTokenSource

이번 포스팅은 C#에서 사용하는 CancellationToken과 CancellationTokenSource를
하나로 묶어 처리하는 기능인 CreateLinkedTokenSource에 대해 작성하였습니다.
📌 CancellationToken과 CancellationTokenSource란?
먼저 앞서 비동기 프로그래밍 게시글에서 작성했던 내용이지만 용어 정리를 먼저 하겠습니다.
- CancellationTokenSource: 취소 요청을 보낼 수 있는 주체입니다.
.Cancel()을 호출하면 이와 연결된 CancellationToken에 취소 신호가 전달됩니다. - CancellationToken: 취소 요청을 수신하고 감지하는 객체입니다.
Task나 메서드에서 이 토큰을 받아들여야 작업 취소를 감지할 수 있습니다.
예제) 기본적인 취소 처리
var cts = new CancellationTokenSource();
var token = cts.Token;
Task task = Task.Run(() =>
{
while (!token.IsCancellationRequested)
{
Console.WriteLine("작업 중...");
Thread.Sleep(500);
}
Console.WriteLine("작업이 취소되었습니다.");
}, token);
Thread.Sleep(2000);
cts.Cancel();
예제에서는 CancellationTokenSource.Cancel() 호출로 인해 작업이 중단됩니다.
이처럼 하나의 CancellationToken은 단일 작업에 대한 취소 신호를 전달할 수 있습니다.
🤔 그런데, 여러 취소 조건이 있다면?
실제 개발을 하다 보면 하나의 작업에 여러 취소 조건이 붙는 경우가 많습니다.
예를 들면
- 사용자가 수동으로 취소
- 네트워크 타임아웃 발생
- 외부 모듈의 요청으로 강제 종료
이처럼 여러 개의 CancellationToken을 하나로 묶어야 하는 상황에서 등장하는 것이 바로 CancellationTokenSource.CreateLinkedTokenSource 입니다.
🔗 CreateLinkedTokenSource로 연결하기
예제 1) 기본적인 사용법
var cts1 = new CancellationTokenSource();
var cts2 = new CancellationTokenSource();
// 두 개의 취소 토큰을 병합
var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
var linkedToken = linkedCts.Token;
Task.Run(() =>
{
while (!linkedToken.IsCancellationRequested)
{
Console.WriteLine("작업 수행 중...");
Thread.Sleep(500);
}
Console.WriteLine("작업이 취소되었습니다.");
});
// 하나만 취소해도 작동!
Thread.Sleep(1000);
cts2.Cancel();
위 코드에서 cts1.Cancel() 또는 cts2.Cancel() 둘 중 하나라도 호출되면 linkedToken은 즉시 취소 상태로 전환됩니다.
이처럼 연결된 토큰은 OR 조건처럼 작동합니다.
예제 2) 사용자 취소 or 타임 아웃 취소
프로젝트를 진행하다 보면 타임 아웃에 대한 작업을 많이 하며,
타임 아웃과 사용자가 UI에서 버튼을 눌러 취소하는 것을 묶어 구현하는 예시입니다.
var userCts = new CancellationTokenSource(); // 사용자 수동 취소
var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(10)); // 타임아웃 취소
using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(userCts.Token, timeoutCts.Token);
try
{
await SomeTaskAsync(linkedCts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("작업이 취소되었습니다.");
}
이제 SomeTaskAsync라는 Task는 다음 조건 중 하나라도 충족되면 취소됩니다:
- 사용자가 userCts.Cancel()을 호출한 경우
- 10초가 초과된 경우 (타임아웃)
🚨 주의할 점
| 항목 | 주의사항 |
| linkedCts는 반드시 Dispose() | 메모리 누수 방지 위해 using 사용 권장 |
| CancellationToken은 읽기 전용 | Cancel()은 CancellationTokenSource에서만 호출 가능 |
| 연결된 토큰은 취소되면 모두 영향 | 연결된 작업은 일괄 취소됨 |
| 예외 처리 | OperationCanceledException 또는 TaskCanceledException을 반드시 잡을 것 |
| 마무리
C#의 CancellationToken은 단순히 작업을 취소하는 것에서 그치지 않고,
CreateLinkedTokenSource를 통해 복잡한 취소 조건을 간결하고 안전하게 처리할 수 있도록 도와줍니다.
여러 개의 취소 조건이 얽힌 복잡한 환경에서도,
예외 처리로 안정적인 코드 구성이 가능해지며, 특히 UI/네트워크/장비 제어 등
실시간 응답성이 중요한 환경에서 필수적인 기능입니다.
궁금하신 점이나 틀린 점이 있으면 댓글로 남겨주세요!
다음 포스팅으로 찾아오겠습니다!