今回は、C#のTaskクラスの使い方を具体例つきでご紹介します。
Taskクラスとは
C#のTaskクラスは、非同期処理や並列処理を簡単に扱うための仕組みです。
メインスレッドをブロックすることなくバックグラウンドで重い処理を実行できるため、アプリケーションの応答性を向上させるのに役立ちます。
非同期プログラミングでは、UIのフリーズ回避や複数の処理を効率的に並行実行するために利用されることが多いです。
基本的な使い方
Taskクラスを使うときは、Task.RunやTask.Factory.StartNewなどを利用して処理をタスク化します。
タスクが終わるまで待機する場合はWaitやResultを使用しますが、async/awaitを活用するとよりシンプルに非同期処理を記述できます。
Task.Runを使う例
まずは最も基本的なTask.Runによるタスク化の例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
using System; using System.Threading.Tasks; public class TaskRunExample { public static void Main() { // Task.Runを用いてバックグラウンドで処理を実行 Task task = Task.Run(() => { // 擬似的な重い処理 Console.WriteLine("処理を開始しました。"); System.Threading.Thread.Sleep(1000); Console.WriteLine("処理が完了しました。"); }); // タスクの完了を待機 task.Wait(); } } |
処理を開始しました。
処理が完了しました。
ここではtask.Wait()を用いてメインスレッドを待機させています。
UIアプリケーションなどでは、メインスレッドをブロックしないようにawaitを使用した非同期実行が推奨されます。
戻り値を持つTask (Task<T>)
タスクが戻り値を返す場合は、Task<T>を用います。
例えば、1から10までの合計値を別スレッドで計算し、結果を取得するコードは次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
using System; using System.Threading.Tasks; public class TaskReturnExample { public static void Main() { // 1~10までの合計を計算するタスク Task<int> sumTask = Task.Run(() => { int sum = 0; for (int i = 1; i <= 10; i++) { sum += i; } return sum; }); // タスクが終わるまで待機し、結果を取得 int result = sumTask.Result; Console.WriteLine($"合計値: {result}"); } } |
合計値: 55
sumTask.Resultはタスク完了まで呼び出し元をブロックします。
UI環境やレスポンスを阻害したくない状況では、後述のasync/awaitパターンを使いましょう。
具体例:async/awaitを使った非同期処理
async/awaitを活用すると、コードの可読性が大幅に向上します。
以下は同様に合計を計算しつつ、非同期で結果を受け取る例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
using System; using System.Threading.Tasks; public class AsyncAwaitExample { // 非同期で合計を計算するメソッド public static async Task<int> CalculateSumAsync() { return await Task.Run(() => { int sum = 0; for (int i = 1; i <= 10; i++) { sum += i; } return sum; }); } public static async Task Main() { // 非同期で計算が終わるまで待機し、結果を取得 int total = await CalculateSumAsync(); Console.WriteLine($"合計値: {total}"); } } |
合計値: 55
このようにawaitを使うと、UIスレッドや呼び出し元をブロックせずにタスクの完了を待機できます。
注意点
Taskクラスを使うときは、ブロッキング操作に注意が必要です。
ResultやWaitをUIスレッド上で使用すると、アプリケーションがフリーズする原因となります。
また、タスク内で例外が発生した場合は、try-catch文やawait時の例外伝播を利用し、確実にエラーをハンドリングしてください。
キャンセルを実装したい場合は、CancellationTokenとCancellationTokenSourceを用いて定期的にキャンセル要求をチェックすると安全です。
まとめ
Taskクラスは非同期処理を手軽に導入できる便利な仕組みです。
並列実行やUIの応答性向上を目的とする際に活躍します。
処理内容やアプリケーション構成に合わせて適切にTaskクラスを活用すると、効率的なプログラム開発が期待できます。