19. Task 조합의 예외·취소 의미론(WhenAll/await rethrow/CancellationToken/미관측 예외)

난이도 상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 주제: Task 조합의 예외·취소 의미론 — Task.WhenAll 의 예외 집계, await 의 rethrow,
//       CancellationToken 협조적 취소, (그리고 WhenAny/async void 의 미관측 예외 함정).
//
// 여러 Task 를 WhenAll 로 묶어 await 하면 "예외가 어떻게 합쳐지고 무엇이 다시 던져지는가",
// 취소된 Task 가 Faulted 가 아니라 Canceled 상태가 되는 이유를 다룬다.
//
// 과제:
//   1) 이 프로그램의 정확한 표준출력을 예측하라(세 줄).
//   2) 두 Task 가 모두 예외를 던졌는데 catch 한 예외 타입/메시지가 왜 그것 하나인지
//      (await 의 rethrow 규칙) 설명하고, all.Exception 에는 무엇이 몇 개 담기는지 밝혀라.
//   3) work 가 왜 Faulted 가 아니라 Canceled(IsCanceled==true) 로 끝나는지
//      (토큰이 일치하는 OperationCanceledException 의 특별 취급) 설명하라.
//   4) (서술) Task.WhenAny 에서 "진 쪽" Task 의 예외가 미관측(unobserved)될 위험과,
//      async void 의 예외가 왜 호출자에서 잡히지 않는지 설명하라.

using System;
using System.Threading;
using System.Threading.Tasks;

public static class Program
{
    static async Task Faulting(string tag, int ms)
    {
        await Task.Delay(ms);
        throw new InvalidOperationException(tag);
    }

    public static async Task Main()
    {
        // (2) WhenAll: 둘 다 던지지만 await 는 "첫 예외" 하나만 rethrow
        var t1 = Faulting("A", 10);
        var t2 = Faulting("B", 30);
        var all = Task.WhenAll(t1, t2);
        try { await all; }
        catch (Exception ex) { Console.WriteLine($"caught {ex.GetType().Name}: {ex.Message}"); }
        Console.WriteLine($"all.IsFaulted={all.IsFaulted} inner={all.Exception?.InnerExceptions.Count}");

        // (3) 협조적 취소: 토큰이 일치하면 Canceled 상태
        using var cts = new CancellationTokenSource();
        var work = Task.Run(async () =>
        {
            for (int i = 0; i < 1000; i++)
            {
                cts.Token.ThrowIfCancellationRequested();
                await Task.Delay(5);
            }
        }, cts.Token);
        cts.Cancel();
        try { await work; }
        catch (OperationCanceledException) { }
        Console.WriteLine($"work.IsCanceled={work.IsCanceled}");
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.