C# では async
/ await
を使うことで、複雑になりがちな非同期処理を直感的に記述できます。従来のコールバックや Task
を直接扱うコードに比べて可読性が高く、同期処理のように自然に書けるのが特徴です。本記事では async
/ await
の基本的な使い方を解説します。
非同期処理の基本構文
非同期処理を行うメソッドには async
修飾子を付けます。その中で await
を使うと、非同期処理が完了するまで待機できますが、スレッドをブロックせずに処理が継続されます。
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
Console.WriteLine("処理開始");
await Task.Delay(2000); // 2秒待機(非同期)
Console.WriteLine("処理終了");
}
}
上記の例では Task.Delay
を使って非同期の待機処理をしています。await
によって自然な手続き型の書き方ができます。
戻り値を持つ非同期メソッド
async
メソッドは Task<T>
を返すことで非同期に値を返せます。
static async Task<int> GetDataAsync()
{
await Task.Delay(1000); // 擬似的に時間のかかる処理
return 42;
}
static async Task Main()
{
int result = await GetDataAsync();
Console.WriteLine(result); // 42
}
非同期メソッドを組み合わせる
複数の非同期処理を組み合わせたい場合も await
で自然に記述できます。
static async Task ProcessAsync()
{
string user = await GetUserNameAsync();
string data = await GetDataAsync(user);
Console.WriteLine($"ユーザー: {user}, データ: {data}");
}
逐次処理が読みやすく書けるのが async/await
のメリットです。
並行処理を行う
複数のタスクを同時に実行して結果を待ちたいときは Task.WhenAll
を使います。
static async Task Main()
{
Task<int> task1 = GetNumberAsync(1);
Task<int> task2 = GetNumberAsync(2);
int[] results = await Task.WhenAll(task1, task2);
Console.WriteLine(string.Join(", ", results));
}
static async Task<int> GetNumberAsync(int num)
{
await Task.Delay(1000);
return num * 10;
}
この場合、2つの処理が同時に進行するため、効率的に実行できます。
例外処理
async/await
の中でも通常の try-catch
が使えます。非同期タスクで例外が発生すると、await
したタイミングで例外がスローされます。
static async Task Main()
{
try
{
await ThrowErrorAsync();
}
catch (Exception ex)
{
Console.WriteLine("例外発生: " + ex.Message);
}
}
static async Task ThrowErrorAsync()
{
await Task.Delay(500);
throw new InvalidOperationException("エラーが発生しました");
}
まとめ
C# の async
/ await
を使うと、非同期処理を同期処理のように直感的に書けます。
async
修飾子を付けたメソッドでawait
が使えるTask
やTask<T>
を返して非同期処理を表現するTask.WhenAll
で並行処理を効率化できるtry-catch
で例外処理も可能
非同期処理は UI 応答性の確保やネットワーク処理の効率化に必須の知識です。async/await
を活用して、シンプルでわかりやすいコードを目指しましょう。