【C#】async/awaitで非同期処理を簡単に書く方法

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 が使える
  • TaskTask<T> を返して非同期処理を表現する
  • Task.WhenAll で並行処理を効率化できる
  • try-catch で例外処理も可能

非同期処理は UI 応答性の確保やネットワーク処理の効率化に必須の知識です。async/await を活用して、シンプルでわかりやすいコードを目指しましょう。