C#でプログラムを作成していると、時間のかかる処理(ファイルの読み書きやネットワーク通信など)を扱うことがあります。このような処理をプログラムのメイン処理と同時に実行する「非同期処理」は、アプリケーションの応答性を向上させる重要な技術です。C# 5.0から導入された「async」と「await」キーワードを使用すると、非同期処理を簡単に実装できます。
この記事では、「async」と「await」キーワードの基本的な使い方から、実践的な例まで詳しく解説します。
「async」と「await」の基本
「async」キーワードは、メソッドが非同期処理を含むことを示します。「await」キーワードは、非同期処理の完了を待つために使用します。
以下は、基本的な使用例です:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("非同期処理を開始します。");
await DoSomethingAsync();
Console.WriteLine("非同期処理が完了しました。");
}
static async Task DoSomethingAsync()
{
await Task.Delay(2000); // 2秒間待機
Console.WriteLine("非同期処理の内容");
}
}
このプログラムでは、Main
メソッドをasync
として定義し、DoSomethingAsync
メソッドをawait
キーワードで呼び出しています。DoSomethingAsync
メソッド内では、Task.Delay
を使用して2秒間の待機を模值しています。
非同期処理の利点
非同期処理を使用すると、時間のかかる処理をバックグラウンドで実行しながら、メインの処理を継続できます。これにより、ユーザーインターフェースの応答性が向上し、全体的なパフォーマンスが改善されます。
例えば、ファイルのダウンロードを非同期で行う例を見てみましょう:
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Console.WriteLine("ファイルのダウンロードを開始します。");
await DownloadFileAsync("https://example.com/largefile.zip");
Console.WriteLine("ダウンロードが完了しました。");
}
static async Task DownloadFileAsync(string url)
{
using (var client = new HttpClient())
{
Console.WriteLine("ダウンロード中...");
string content = await client.GetStringAsync(url);
Console.WriteLine($"ダウンロードしたファイルのサイズ: {content.Length} バイト");
}
}
}
この例では、DownloadFileAsync
メソッド内でHttpClient
を使用してファイルをダウンロードしています。await
キーワードを使用することで、ダウンロードが完了するまでプログラムが一時停止され、完了後に処理が再開されます。
複数の非同期処理の扱い
複数の非同期処理を同時に実行したい場合は、Task.WhenAll
メソッドを使用します:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
Task task1 = DoTaskAsync("タスク1", 2000);
Task task2 = DoTaskAsync("タスク2", 1000);
Task task3 = DoTaskAsync("タスク3", 3000);
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("すべてのタスクが完了しました。");
}
static async Task DoTaskAsync(string taskName, int delay)
{
await Task.Delay(delay);
Console.WriteLine($"{taskName} が完了しました。");
}
}
この例では、3つの非同期タスクを同時に開始し、Task.WhenAll
を使用してすべてのタスクの完了を待っています。
非同期処理のエラーハンドリング
非同期処理でも、通常の同期処理と同様にtry-catchブロックを使用してエラーをハンドリングできます:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
try
{
await DoSomethingRiskyAsync();
}
catch (Exception ex)
{
Console.WriteLine($"エラーが発生しました: {ex.Message}");
}
}
static async Task DoSomethingRiskyAsync()
{
await Task.Delay(1000);
throw new Exception("何か問題が発生しました");
}
}
この例では、DoSomethingRiskyAsync
メソッド内で例外をスローしていますが、Main
メソッド内のtry-catchブロックでキャッチされます。
まとめ
C#の「async」と「await」キーワードを使用することで、複雑な非同期処理を簡潔に記述できます。これにより、応答性の高いアプリケーションを効率的に開発できます。
非同期プログラミングは最初は少し難しく感じるかもしれませんが、実践を重ねることで自然に書けるようになります。ファイルの入出力、データベース操作、ネットワーク通信など、時間のかかる処理を扱う際には、積極的に非同期プログラミングを活用しましょう。
「async」と「await」を使いこなすことで、より効率的で高性能なC#アプリケーションを開発する力が身につきます。
コメント