21. AsyncLocal<T> 와 ExecutionContext 흐름 (await 를 가로지르는 컨텍스트)
난이도 최상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// [주제] AsyncLocal<T> 와 ExecutionContext 흐름: await 를 가로지르는 논리적 컨텍스트
// 게임 서버에서 "현재 요청의 플레이어 ID·트레이스 ID" 같은 값을 파라미터로
// 일일이 넘기지 않고 흐름 전체에 실으려면 AsyncLocal 을 쓴다. 이 값은 스레드가
// 아니라 "논리적 비동기 흐름" 을 따라 전파된다. 반면 [ThreadStatic] 은 물리
// 스레드에 묶인다.
//
// [과제]
// 1) 출력 A~F 가 각각 무엇을 출력할지 예측하라(특히 D 와 F 에 주의).
// 2) AsyncLocal.Value 를 설정하면 그 변경이 "아래로(호출된 async)" 는 흐르지만
// "위로(호출자)" 는 흐르지 않는 이유를, ExecutionContext 캡처/복원과
// copy-on-write 관점에서 설명하라. 또 같은 목적을 [ThreadStatic] 으로
// 구현하면 await 이후 왜 값이 사라질 수 있는지 대비해 설명하라.
// (내부 동작 설명은 answer.md 참조 — 먼저 스스로 예측/설명해 볼 것.)
using System;
using System.Threading.Tasks;
class AsyncContextDemo
{
static AsyncLocal<int> Ctx = new AsyncLocal<int>();
static async Task Main()
{
Ctx.Value = 1;
Console.WriteLine("A: " + Ctx.Value);
await Child();
Console.WriteLine("D: " + Ctx.Value);
var t1 = Branch(10);
var t2 = Branch(20);
int r1 = await t1;
int r2 = await t2;
Console.WriteLine("E: " + r1 + "," + r2);
Console.WriteLine("F: " + Ctx.Value);
}
static async Task Child()
{
Console.WriteLine("B: " + Ctx.Value);
Ctx.Value = 42;
await Task.Yield();
Console.WriteLine("C: " + Ctx.Value);
}
static async Task<int> Branch(int v)
{
Ctx.Value = v;
await Task.Yield();
return Ctx.Value;
}
} 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.