はじめに
C#の学習を進めていくにあたり、非同期処理は壁に感じる人は多いのではないか(多分)
自分も当初、理解に苦しんだこともあり、初学者向けに簡単に解説しておきたい。
非同期処理とは
非同期処理とは、時間のかかる処理を実行する際に、プログラム全体の動作を止めることなく並行して処理を進める仕組みである。
特に、UI アプリケーションにおいては、重い処理(例: データベースアクセスやネットワーク通信)を同期的に実行すると、処理が完了するまでUIがフリーズしてしまう。
しかし、非同期処理を使うことで、UIをブロックせずにスムーズな動作を維持できる。
C#における非同期処理
非同期処理を文章だけで理解してもらうのは困難だと思ったので図を作ってみた↓
図左側:同期処理
-
「main」内で処理①から順番に処理④まで実行される
-
各処理が順番に実行され、前の処理が完了するまで次の処理は開始されない
-
処理②(重い処理) も他の処理と同じ流れで順番に実行されるため、処理②の完了を待つ間、他の処理は停止する
図右側:非同期処理
-
「main」内で処理①が実行され、その後すぐに処理③と処理④が実行される
-
処理②(重い処理) は async により別スレッドで実行され、await を使用することで「main」にTask型のデータを返し、処理②の完了を待たずに他の処理を進めることができる
-
Task 型を使用することで非同期に処理を進めつつ、結果が必要なタイミングで待機することが可能
戻り値のない非同期メソッドの例
説明はコメントアウトに記載しています。
class Program
{
static void Main(string[] args)
{
Console.WriteLine("非同期処理を開始します...");
// 非同期メソッドを呼び出す
DelayAsync(3000); // 3秒待つ
// 非同期メソッドの完了を待たず実行
Console.WriteLine("他の処理を実行中...");
// 非同期処理の完了を待つ
Console.ReadLine(); // 非同期処理が完了するのを待機(待たないと非同期メソッドが完了する前に処理が終了してしまう)
}
// 戻り値なしの非同期メソッド
static async Task DelayAsync(int milliseconds)
{
await Task.Delay(milliseconds); // 指定されたミリ秒だけ待つ
Console.WriteLine("処理が完了しました!");
}
}
返り値がある非同期メソッドの例
class Program
{
static void Main(string[] args)
{
Console.WriteLine("非同期処理を開始します...");
// 非同期メソッドを呼び出す
Task<string> task = DelayAsync(3000); // 3秒待つ
// 非同期メソッドの完了を待たず実行
Console.WriteLine("他の処理を実行中...");
// 非同期処理が完了するのを待機(待たないと非同期メソッドが完了する前に処理が終了してしまう)
string result = task.Result; // 非同期メソッドの戻り値を取得
Console.WriteLine(result);
}
// 非同期メソッド
static async Task<string> DelayAsync(int milliseconds)
{
await Task.Delay(milliseconds); // 指定されたミリ秒だけ待つ
return "処理が完了しました!";
}
}
キーワード | 使う場所 | 説明 |
---|---|---|
Task |
メソッドの戻り値の型として | 非同期メソッドが返す型。戻り値なしなら Task 、戻り値ありなら Task<T> を使う。 |
async |
メソッド定義の前 | 非同期メソッドとして定義するために使う。必ず戻り値の型の前に付ける。 |
await |
非同期メソッド内で非同期タスクを待つ | 非同期タスクの完了を待機するために使う。Task を返すメソッドでのみ使用可能。 |