はじめに
非同期処理は、パフォーマンスを最大限に引き出すために非常に重要です。C#では、タイマーや遅延処理を使用して、指定した時間にタスクを実行したり、一定間隔で繰り返しタスクを実行することができます。本記事では、C#での日時に関連した非同期処理にフォーカスし、タイマーや遅延処理の基本的な使い方から応用例までを解説します。
非同期処理の基本概念
C#では、非同期処理は主にasync/awaitを使って行います。非同期処理を活用することで、時間のかかる処理が完了するのを待つ間、他のタスクを並行して実行できます。これにより、UIのフリーズやサーバーのレスポンス遅延を防ぐことが可能です。
非同期処理では、日時に関連したタイマーや遅延処理が多くの場面で使用されます。例えば、一定の時間が経過した後に特定の処理を実行したり、定期的にデータをチェックするなどのシナリオが考えられます。
Task.Delayを使った遅延処理の実装
Task.Delayは、指定した時間が経過するまで非同期に処理を停止させるための便利なメソッドです。遅延処理をシンプルに実装でき、タイマーやリトライ処理の際に有用です。
基本的なTask.Delayの使用例
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main(string[] args)
{
Console.WriteLine("処理開始");
await Task.Delay(5000); // 5秒間の遅延
Console.WriteLine("5秒後に実行");
}
}
このコードでは、プログラムは「処理開始」と出力した後、5秒間待機してから「5秒後に実行」と出力します。Task.Delayを使うことで、非同期に待機しつつ他の処理を続けることができます。
遅延処理の応用例:リトライ処理
Task.Delayは、エラー時のリトライ処理にも応用できます。たとえば、APIの呼び出しが失敗した場合に、数秒間の遅延を挟んで再試行する場合などです。
public async Task RetryWithDelayAsync(int maxRetries)
{
int retries = 0;
while (retries < maxRetries)
{
try
{
// API呼び出しなどの処理
Console.WriteLine("処理中...");
break; // 成功した場合はループを抜ける
}
catch (Exception)
{
retries++;
Console.WriteLine($"リトライ {retries} 回目...");
await Task.Delay(2000); // 2秒待機して再試行
}
}
}
この例では、API呼び出しが失敗した場合、2秒の遅延を挟んでリトライを行っています。
System.Timers.Timerを使ったタイマーの実装
System.Timers.Timerは、指定した時間間隔で定期的に処理を実行するタイマー機能を提供します。非同期でタイマーを使用することで、指定された時間間隔でバックグラウンド処理を実行することが可能です。
基本的なタイマーの使用例
using System;
using System.Timers;
public class TimerExample
{
private static Timer _timer;
public static void Main()
{
// タイマーの初期化(2秒ごとにイベントを発生させる)
_timer = new Timer(2000);
_timer.Elapsed += OnTimedEvent;
_timer.AutoReset = true; // 繰り返し実行
_timer.Enabled = true;
Console.WriteLine("タイマー開始。Enterキーを押して終了します...");
Console.ReadLine();
}
// タイマーが経過したときに実行されるイベント
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
Console.WriteLine("タイマーイベント発生: {0:HH:mm:ss.fff}", e.SignalTime);
}
}
この例では、2秒ごとにタイマーイベントが発生し、イベントハンドラ内で日時が表示されます。タイマーは非同期に動作し、メインスレッドは影響を受けません。
タイマーの停止
タイマーを停止するには、Timer.Stopメソッドを使用します。
CancellationTokenによる非同期処理のキャンセル
非同期処理を途中でキャンセルする必要がある場合、CancellationTokenを使用します。これは、タイマーや遅延処理が実行される前に処理をキャンセルしたり、中断するために便利です。
CancellationTokenを使った遅延処理のキャンセル例
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
public static async Task Main(string[] args)
{
CancellationTokenSource cts = new CancellationTokenSource();
// 5秒後にキャンセルを発行
Task.Run(() =>
{
Thread.Sleep(5000);
cts.Cancel();
});
try
{
Console.WriteLine("遅延処理開始...");
await Task.Delay(10000, cts.Token); // 10秒間の遅延(5秒後にキャンセル)
}
catch (TaskCanceledException)
{
Console.WriteLine("処理がキャンセルされました");
}
}
}
この例では、Task.Delayによる10秒間の遅延処理を途中でキャンセルしています。5秒後にCancellationTokenSourceがキャンセルを発行し、TaskCanceledExceptionがスローされます。
実践的な非同期処理のシナリオ
シナリオ1: 一定間隔でAPIをポーリング
バックグラウンドで一定間隔ごとにAPIからデータを取得し、UIを更新する場合、System.Timers.Timerを使って定期的にAPIをポーリングできます。
private static Timer _apiPollingTimer;
public static void StartApiPolling()
{
_apiPollingTimer = new Timer(60000); // 1分ごとにAPIを呼び出し
_apiPollingTimer.Elapsed += async (sender, e) => await CallApiAsync();
_apiPollingTimer.AutoReset = true;
_apiPollingTimer.Enabled = true;
}
public static async Task CallApiAsync()
{
// API呼び出しの処理
Console.WriteLine("APIを呼び出し中...");
}
シナリオ2: ユーザー入力の後、一定時間後に処理を実行
ユーザーが入力を完了してから、数秒待ってから実行するような遅延処理もよくあります。この場合、Task.Delayを使って一定時間待機する処理を実装できます。
public static async Task ExecuteAfterDelayAsync()
{
Console.WriteLine("ユーザー入力待機中...");
await Task.Delay(3000); // 3秒の遅延
Console.WriteLine("処理実行");
}
まとめ
C#での非同期処理は、タイマーや遅延処理によって多くのシナリオに対応できます。非同期処理を正しく実装することで、システムのパフォーマンスやユーザーエクスペリエンスを向上させることが可能です。
Task.Delay: 遅延処理をシンプルに実装。System.Timers.Timer: 定期的な処理を非同期に実行するために便利。CancellationToken: 非同期処理を途中でキャン

コメント