AggregateException は「複数の例外をまとめた袋」。async / Task.WhenAll / Parallel でよく出る。中身をほどかないと本当の原因が見えない。
InnerExceptions(複数)または InnerExceptionFlatten() してから列挙await した例外は多くの場合「中身の例外」がそのまま再スローされる(Aggregate に包まれにくい)task.Result / task.Wait() / Task.WaitAll だと Aggregate になりやすいTask.WhenAll のあとに .Wait() / .ResultParallel.For / PLINQ の集約例外task.Wait()try
{
Task.WaitAll(tasks);
}
catch (AggregateException ex)
{
foreach (var e in ex.Flatten().InnerExceptions)
{
// 実際の原因(HttpRequestException など)をログ
Console.WriteLine(e.GetType().Name + ": " + e.Message);
}
}
Flatten() … 入れ子の Aggregate を平らにするInnerExceptions … 平らにしたあとの個別例外// 推奨: await(1件失敗でもその例外が見えやすい)
try
{
await Task.WhenAll(tasks);
}
catch (Exception ex)
{
// WhenAll は「最初に観測した例外」が来ることも。
// 全失敗を見たいなら tasks を個別に確認する
}
// 全タスクの例外を拾う例
var results = await Task.WhenAll(
tasks.Select(async t =>
{
try { await t; return (Exception?)null; }
catch (Exception e) { return e; }
}));
ポイント: ブロッキング(Wait/Result)をやめて await すると、Aggregate とデッドロックの両方を減らせる。
InnerException だけ見て 2 件目以降を落とすFlatten().InnerExceptions で見る