-
C# 비동기의 복병, TaskCanceledException 완벽 대처법 (타임아웃 해결)개발/C# 2026. 1. 26. 16:56반응형
안녕하세요! 요즘 C# 개발의 대세는 역시 비동기(async/await)죠. 특히 네트워크로 데이터를 주고받거나 대용량 파일을 읽을 때 필수입니다. 그런데 코드를 잘 짜놓고 돌리다 보면 갑자기 이런 메시지를 마주할 때가 있습니다.
에러 메시지: System.Threading.Tasks.TaskCanceledException: A task was canceled.
"내가 취소한 적도 없는데 왜 취소됐다는 거야?"라며 당황하신 적 있으시죠? 오늘은 이 에러가 왜 발생하는지, 그리고 어떻게 하면 우아하게 '예외 처리'를 할 수 있는지 알려드릴게요.
1. 원인은 보통 '타임아웃(Timeout)'입니다
이 에러는 보통 **HttpClient**를 쓰거나 **CancellationToken**을 사용할 때 발생합니다.
- 상황: 데이터를 요청했는데 서버가 너무 느려요.
- 결과: "10초만 기다리기로 했는데 소식이 없네? 에잇, 취소!" 하고 프로그램이 스스로 작업을 중단해 버리는 겁니다.
이건 에러라기보다 프로그램이 무한정 대기 상태(Freezing)에 빠지는 걸 막아주는 아주 기특한 보호 본능인 셈이죠.
2. 실전 코드: "기다리다 지쳐 취소될 때"
가장 흔한 HttpClient 예시를 볼까요?
public async Task DownloadDataAsync() { using var client = new HttpClient(); // 5초만 기다리겠다고 설정 client.Timeout = TimeSpan.FromSeconds(5); try { // 5초 안에 응답이 안 오면 여기서 TaskCanceledException 발생! var result = await client.GetStringAsync("https://slow-api-server.com"); Console.WriteLine(result); } catch (TaskCanceledException ex) { // "에러다!"가 아니라 "서버가 너무 느려서 일단 끊었어"라고 이해해야 합니다. Console.WriteLine("서버 응답이 너무 늦어 연결을 취소했습니다."); } catch (Exception ex) { Console.WriteLine($"기타 에러: {ex.Message}"); } }3. 고수들은 'CancellationToken'을 씁니다
실무에서는 사용자가 직접 "취소" 버튼을 누르거나, 프로그램이 종료될 때 진행 중인 작업을 멈추기 위해 **CancellationTokenSource**를 명시적으로 사용합니다.
CancellationTokenSource cts = new CancellationTokenSource(); // 3초 뒤에 무조건 취소하도록 예약 cts.CancelAfter(3000); try { await LongRunningJobAsync(cts.Token); } catch (OperationCanceledException) // TaskCanceledException의 부모 격입니다. { Console.WriteLine("사용자 혹은 시스템에 의해 작업이 중단되었습니다."); }4. (꿀팁) 에러인지 취소인지 구분하는 법
TaskCanceledException이 터졌을 때, 이게 시간이 다 돼서(Timeout) 그런 건지, 아니면 **코드에서 취소(Cancel)**를 시킨 건지 헷갈릴 때가 있죠?
- ex.CancellationToken.IsCancellationRequested 가 false라면? -> 십중팔구 타임아웃 때문입니다.
- **true**라면? -> 누군가(혹은 시스템이) 명시적으로 취소 버튼을 누른 겁니다.
마무리하며
**TaskCanceledException**을 만났을 때 당황하지 마세요. 이건 여러분의 프로그램이 '먹통'이 되지 않도록 AI(아니, 닷넷 런타임 ㅎㅎ)가 열일하고 있다는 증거니까요. 이제 try-catch로 이 녀석을 잘 달래주기만 하면 됩니다!
오늘 여러분의 비동기 코드는 안녕하신가요? 혹시 타임아웃 때문에 고생 중이라면 지금 바로 Timeout 설정을 체크해 보세요!
반응형'개발 > C#' 카테고리의 다른 글
[C#] MQTTnet + Blazor: 센서 데이터를 실시간 웹 대시보드로 구현하기 (PostgreSQL 연동) (0) 2026.01.30 C# 메모리 누수, 이벤트 핸들러 완벽 관리법 (0) 2026.01.30 C# 인터페이스를 활용한 의존성 주입(DI) 완벽 이해 (0) 2026.01.23 C# 설계의 핵심: 인터페이스 vs 추상 클래스, 5분 만에 끝내는 완벽 비교 (0) 2026.01.23 [C#] "파일을 찾을 수 없습니다" – FileNotFoundException, 경로의 함정 (1) 2026.01.22