• システム開発に関わる内容をざっくりと書いていく

C# ConfigureAwait(false) が必要な場面・不要な場面

ConfigureAwait(false) は「続きを元の同期コンテキストに戻さない」指定。ライブラリや ASP.NET Core の扱いが混同されやすいので、場面で分ける。

先に結論

  • ライブラリ/共通ヘルパでは ConfigureAwait(false) を付けることが多い
  • ASP.NET Core アプリコードでは原則不要(同期コンテキストが載らない)
  • UI アプリ(古い ASP.NET / WinForms / WPF)では UI スレッド復帰が必要な箇所と不要な箇所を分ける
  • .Result / .Wait() との併用はデッドロックの温床

必要な場面

  • NuGet 向けライブラリ内の await(呼び出し側コンテキストに依存しない)
  • UI スレッド以外で続けてよい重い I/O の後続
  • 同期コンテキストがあるホストで、不要な復帰コストを避けたいとき

不要な場面

  • ASP.NET Core のコントローラ/ハンドラの大半
  • 続きで UI コントロールを触る必要があるコード(false にすると別スレッド)
  • すでに同期コンテキストが無い実行環境での機械的な付け足し(害は少ないが必須ではない)
// ライブラリ内の例
var data = await stream.ReadAsync(buf, ct).ConfigureAwait(false);
return Parse(data);

デッドロックとの関係

  • 同期コンテキスト上で .Result 待ち + 続きがコンテキスト復帰待ち、が典型
  • 根本対策は「async を最後まで」「ブロッキングしない」
  • ConfigureAwait(false) は回避策の一つだが、設計の代替にはならない

関連: async/await デッドロック・ハング

ざっくりまとめ

  • ライブラリは false、ASP.NET Core アプリは原則不要
  • UI は復帰が要る await を見極める
  • ブロッキング呼び出しをやめるのが本筋

関連記事