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 を見極める
- ブロッキング呼び出しをやめるのが本筋
関連記事