ConfigureAwaitと例外の伝播
コンテキストのキャプチャとConfigureAwait(false)を理解し、awaitとブロッキング処理における例外処理を学び、AggregateExceptionとベストプラクティスを確認します。
「ConfigureAwaitと例外の伝播」はCoddyKit上の無料C# Academyレッスンです。 これはレッスン3/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC# Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C# Academyコースには全3レッスンが含まれています。
コンテキストと例外
目標:
- コンテキストの捕捉とは何かを理解します
- ConfigureAwait(false) をいつ使うかを学びます
- await で例外がどのように伝播するかを理解します
- ブロッキングによって AggregateException が発生する理由を理解します
ライブラリのベストプラクティス
ライブラリのメソッドでは、所有していない UI や Web のコンテキスト上で再開されないように、ConfigureAwait(false) を使用してください。
using System;
using System.Threading.Tasks;
public static class NetLib
{
// Library code should not assume a UI context. Use ConfigureAwait(false).
public static async Task<string> FetchAsync()
{
await Task.Delay(100).ConfigureAwait(false); // do not capture context
return "payload";
}
}
public class Program
{
public static void Main(string[] args)
{
// Console apps typically have no SynchronizationContext; this still runs fine.
string s = NetLib.FetchAsync().GetAwaiter().GetResult();
Console.WriteLine("Got: " + s);
}
}
コンテキストのルール
コンテキストの捕捉:
- デフォルトの await は、捕捉されたコンテキスト(UI/ASP.NET)で再開しようとします
- ConfigureAwait(false) は、捕捉せずにスレッドプール上で再開するよう指示します
- 呼び出し元がコンテキストのスレッドをブロックした場合に、デッドロックの回避に役立ちます
- UI コードではコントロールを更新するためにコンテキストが必要になる場合がありますが、通常、ライブラリコードでは必要ありません
Await と例外
await すると、例外は元の例外型のまま伝播するため、通常どおりに catch できます。
using System;
using System.Threading.Tasks;
public class Program
{
static async Task<string> BoomAsync()
{
await Task.Delay(50);
throw new InvalidOperationException("boom");
}
public static void Main(string[] args)
{
// With await (inside async), exceptions rethrow as the original type.
try
{
string r = BoomAsync().GetAwaiter().GetResult(); // emulate await in Main
Console.WriteLine(r);
}
catch (InvalidOperationException ex)
{
Console.WriteLine("Caught: " + ex.GetType().Name + " - " + ex.Message);
}
}
}
ブロッキングとエラー
.Result や .Wait() でブロックすると、エラーは AggregateException にラップされます。エラーの伝播を明確にするには await を優先します。
using System;
using System.Threading.Tasks;
public class Program
{
static async Task<int> FailsAsync()
{
await Task.Delay(30);
throw new ArgumentException("bad arg");
}
public static void Main(string[] args)
{
try
{
// Blocking with .Result wraps the exception into AggregateException
int x = FailsAsync().Result;
Console.WriteLine(x);
}
catch (AggregateException ae)
{
Exception inner = ae.InnerException;
Console.WriteLine("AggregateException -> " + (inner == null ? "null" : inner.GetType().Name));
}
}
}
ベストプラクティス
ガイドライン:
- ライブラリでは ConfigureAwait(false) を使用します
- UI や Web では、コンテキストが必要な場合に呼び出し元のスレッドで await します
- .Result/.Wait() を避け、await で元の例外を捕捉します
- 必要に応じて、コンテキストを考慮したメッセージを付けてログを記録し、再スローします
ConfigureAwait の動作
まとめ
まとめ: ライブラリでは ConfigureAwait(false) を使用し、UI や Web のコードではコンテキストが必要なタイミングを判断させます。例外の伝播を明確にするには await を優先します。ブロッキングはエラーをラップし、デッドロックの危険を招きます。
よくある質問
「ConfigureAwaitと例外の伝播」レッスンは無料ですか?
はい。「ConfigureAwaitと例外の伝播」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C# Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C# Academyコースには全3レッスンが含まれています。
「ConfigureAwaitと例外の伝播」で何を学びますか?
コンテキストのキャプチャとConfigureAwait(false)を理解し、awaitとブロッキング処理における例外処理を学び、AggregateExceptionとベストプラクティスを確認します。 ブラウザで直接実行するハンズオンコードでC# Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C# Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC# Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/3です。
「ConfigureAwaitと例外の伝播」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC# Academyレッスンでコードを書いて実行できますか?
はい。すべてのC# Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Task/ValueTaskとasyncステートマシン(概念)
- 非同期処理の注意点:sync-over-asyncとデッドロック
- ConfigureAwaitと例外の伝播