C# の async/await で「終わらない」「UI やリクエストが固まる」ときは、例外より待ち方の設計が原因なことが多い。
この記事では、デッドロックっぽく見える待ちと、よくある直し方をざっくり整理する。
await を貫通させるTask.Result / Wait() で同期待ちしない// NG例(同期待ち)
var data = GetDataAsync().Result;
GetDataAsync().Wait();
待っているスレッドと、続きを実行したいスレッドがぶつかり、進まなくなることがある。
public string GetName()
{
return GetNameAsync().GetAwaiter().GetResult(); // 境界で同期化
}
ライブラリ境界などどうしても必要な場合以外は避けた方が安全。
var t1 = LoadAAsync();
var t2 = LoadBAsync();
await Task.WhenAll(t1, t2);
逆に、順番に await しすぎて遅くなるケースもある。固まる系と遅い系は切り分けて考える。
Wait / Result / GetResult がないか確認async Task で通すCancellationToken で無限待ちを防ぐpublic async Task<IActionResult> GetAsync(CancellationToken ct)
{
var data = await _service.GetAsync(ct);
return Ok(data);
}
Result / Wait は第一容疑者