C#で指定した時間だけ処理を待機させる方法としては、Thread.SleepメソッドとTask.Delayメソッドがあります。両者はともに処理を一定時間停止できるメソッドですが、その挙動は異なります。
本記事ではC#における処理の一時停止方法について、初心者エンジニアにもわかりやすく解説します。SleepとDelayの違いや使い分けを詳しく解説するので、C#で一定時間処理を止める方法を習得しましょう。
目次
閉じる
1.C#で処理を数秒待つ方法【Sleep/Delayの基本】
C#で処理を一時停止するには、以下の2つの方法があります。
Thread.Sleepメソッド
Task.Delayメソッド
この章ではそれぞれの特徴と使い方について紹介します。
C# Sleepメソッドの概要と使い方
Thread.Sleepメソッドは、現在実行中のスレッドを指定された時間だけ一時停止させます。System.Threading.Thread.Sleepを使用し、引数には停止させる時間(ミリ秒単位)を指定します。
Sleepメソッドの使用例は以下のとおりです。
using System; using System.Threading;
{ static void Main() { Console.WriteLine("処理開始"); Thread.Sleep(2000); // 2秒間停止 Console.WriteLine("2秒後に処理再開"); } } |
Thread.Sleepメソッドは、主に同期的な処理の中で指定時間待機したいときに使用します。
ただ、このメソッドは呼び出したスレッド自体を完全に停止させる点に注意が必要です。Thread.Sleepメソッドを呼び出すとそのスレッドの実行が完全に停止するため、UIスレッドで使用するとアプリケーション全体がフリーズしたように見える場合があります。
C# Delayメソッドの概要と使い方
Task.Delayメソッドは、指定された時間だけ非同期的に処理を待機させるためのメソッドです。Thread.Sleepと異なり、スレッドをブロックすることなく待機中も他の処理を実行できます。
Task.Delayメソッドもミリ秒単位で待機時間を指定します。async修飾子をメソッドに付与してTask.Delayの呼び出し箇所でawaitキーワードを使用して使用します。
using System; using System.Threading.Tasks;
{ public static async Task Main(string[] args) { Console.WriteLine("非同期処理を開始します。");
await Task.Delay(3000); // 3000ミリ秒 = 3秒
} } |
上記のコード例では、async Task Mainメソッド内で await Task.Delay(3000) が呼び出されています。これにより、3秒間の待機中もスレッドはブロックされず他のタスクを実行でき、3秒経過後にawait の次の行の処理が実行されます。
Delayメソッドを使うことでスレッドをブロックせずに一定時間待機できるため、UI操作を含むアプリケーションや複数の非同期処理を並列して実行する場合に使用します。
C# Task.Delayメソッドが効かない原因
Task.Delayメソッドが期待通りに動作しない場合、多くはawaitを付けずに呼び出していることが原因です。
Task.Delayは非同期タスクを返すだけで、そのままでは待機せずすぐに次の処理へ進んでしまいます。この非同期タスクが完了するのを待つためには、await キーワードを使用する必要があります。
Task.Delayメソッドが効かないコードの例は以下の通りです。
using System; using System.Threading.Tasks;
{ // async修飾子をMainメソッドに付与 public static async Task Main(string[] args) { Console.WriteLine("処理を開始します。");
Task.Delay(3000); // この呼び出しはすぐに完了し、待機しない
Console.WriteLine("Task.Delayの直後に実行されました。"); } } |
上記の例では、Task.Delay(3000) にawait がないため、プログラムはそのタスクの完了を待たずに次の行を実行してしまいます。結果として3秒間の待機は行われません。
正しいコードは以下のとおりです。
using System; using System.Threading.Tasks;
{ public static async Task Main(string[] args) { Console.WriteLine("処理を開始します。");
await Task.Delay(3000);
Console.WriteLine("3秒後に実行されました。"); } } |
await を使用することで、Task.Delay(3000) によって返されたタスクが完了するまでMain メソッドの実行が一時停止します。そして、3秒経過後に次の行の処理が再開されます。
Task.Delayが効かない場合は、まずawaitキーワードが正しく使用されているかを確認しましょう。また、Task.Delayを呼び出しているメソッドがasyncキーワードで修飾されているかも確認してください。awaitはasyncメソッド内でのみ使用できます。
2.C# Sleep/Delayの違いと使い分け
Thread.SleepとTask.Delayはどちらも処理を一時停止させるために使用されますが、その仕様や利用シーンには大きな違いがあります。
この章ではThread.SleepとTask.Delayの違いや使い分けについて紹介します。
C# SleepとDelayの違い
Thread.SleepとTask.Delayの最も大きな違いは、スレッドをブロックするかどうかです。
Thread.Sleepは、指定した時間だけ現在のスレッドの処理を完全に停止します。そのため、UIスレッドでThread.Sleepを呼び出すと画面の更新やユーザー入力の受付ができなくなり、アプリケーションが応答しない状態になります。
一方、Task.Delayは非同期タスクとして一定時間後に処理を再開します。スレッド自体をブロックしないため、UIの応答性を維持したまま待機処理を実現できます。
Thread.SleepとTask.Delayの主な違いは以下のとおりです。
特徴 | Thread.Sleep | Task.Delay |
---|---|---|
動作 | 同期的 | 非同期的 |
スレッド制御 | 呼び出したスレッドを完全に停止させる | スレッドをブロックせず、待機中に他の処理を実行可能 |
UIへの影響 | フリーズする | フリーズしない |
リソース効率 | スレッドリソースを占有 | スレッドリソースを効率的に利用 |
主な用途 | シンプルなコンソールアプリや、スレッドブロックが問題ない場面 | UIアプリケーションや複数の非同期処理を含むシステム |
C# SleepとDelayの使い分け
Thread.SleepとTask.Delayの使い分けのポイントは同期的に待機するかどうかです。同期処理内で一時的に処理を止めたい場合は、Thread.Sleepを使用します。一方、非同期処理やUIスレッドでの遅延処理には、Task.Delayを使用します。
Thread.Sleep が適しているケースは以下のとおりです。
コンソールアプリケーションなど、UIを持たないプログラム
シンプルな実装で十分な場合
明示的にスレッドを停止したい場合
非同期処理の導入が困難なレガシーシステムで、既存の動作を維持する必要がある場合
Task.Delayが適しているケースは以下になります。
WPF、Windows Forms、ASP.NETなどのUIを持つアプリケーション
複数の非同期処理を並行して実行する必要がある場合
スレッドリソースを効率的に使用したい場合
サーバーサイドアプリケーション (ASP.NET Coreなど)の場合
最近ではスレッドを不必要にブロックすることを防ぐために、Task.Delayを使うことが多いです。特にGUIアプリケーションの場合は必ずTask.Delayを使用すると覚えておきましょう。
関連記事
C#とは?基本文法や特徴、メリット、開発分野まで初心者に必要な情報をわかりやすく解説
.NET Frameworkとは?バージョン確認から.NETの違い、インストール、よくあるエラー解決策まで解説
3.実践的なコード例で学ぶC# Sleepの活用法
最近ではThread.SleepよりもTask.Delayを使うことが多いですが、特定の状況においてはThread.Sleepを使うこともあります。
この章では、Thread.Sleepのいくつかの具体的な使い方を見ていきましょう。
Thread.Sleep(0)の意味と使い方
Thread.Sleep(0)は、「現在のスレッドをただちに再スケジューリングする」という意味を持ちます。これは他の同優先度のスレッドにCPUの実行権を譲るために使われます。CPUに空きがなければすぐに処理が再開されます。
Thread.Sleep(0)によるスレッドの切り替えの例は以下のとおりです。
using System; using System.Threading;
{ static void Main(string[] args) { Console.WriteLine("スレッドの優先順位による実行例");
// 複数のスレッドを起動 for (int i = 0; i < 5; i++) { int threadNum = i; Thread t = new Thread(() => WorkerMethod(threadNum)); t.Start(); }
Console.ReadKey(); }
static void WorkerMethod(int threadNum) { for (int i = 0; i < 3; i++) { Console.WriteLine($"スレッド {threadNum}: 処理中 {i}"); Thread.Sleep(0); // 他のスレッドに実行権を譲る } } } |
このコードでは5つのスレッドを並行実行して各スレッド内でThread.Sleep(0)を呼び出すことで、他のスレッドにも均等に実行の機会を与えています。
Thread.Sleep(0)は以下のような場面で活用できます。
CPU負荷の高い処理を行う中で、他のスレッドにも実行の機会を与えたい場合
スレッドスケジューリングの公平性を確保したい場合
ただし、スレッドスケジューリングの詳細はOSによって異なるため、Thread.Sleep(0)の効果は実行環境によって変わる可能性があることに注意が必要です。
C# Sleepメソッドで1秒後に実行する方法
1秒後に処理を実行したい場合、Thread.Sleep(1000)を使います。
Thread.Sleepで1秒後に実行するコード例は以下のとおりです。
using System; using System.Threading;
{ public static void Main(string[] args) { Console.WriteLine("処理Aを実行します。時刻: " + DateTime.Now.ToString("HH:mm:ss"));
Console.WriteLine("1秒待機します..."); Thread.Sleep(1000); // 1000ミリ秒 = 1秒
} } |
このコードを実行すると「処理A」のメッセージが表示された後、Thread.Sleep(1000)によって1秒間スレッドが停止し、「処理B」のメッセージが表示されます。
なお、Thread.SleepはUIスレッドをブロックするため、GUIアプリケーションで使用するとアプリケーションがフリーズします。GUIアプリケーションでは、非同期的に待機するTask.Delayを使用しましょう。
using System; using System.Threading.Tasks;
{ public static async Task Main(string[] args) { Console.WriteLine("非同期処理Aを実行します。時刻: " + DateTime.Now.ToString("HH:mm:ss"));
Console.WriteLine("1秒非同期的に待機します..."); await Task.Delay(1000); // 1000ミリ秒 = 1秒
} } |
C# Sleepメソッドでマイクロ秒待機する方法
Thread.Sleepメソッドは引数をミリ秒単位で受け取るため、マイクロ秒(1ミリ秒の1/1000)単位での待機を直接指定できません。
マイクロ秒単位の高精度な待機が必要な場合は、Stopwatchクラスなどを使ったループ処理で近似的に実現します。
using System; using System.Diagnostics; using System.Threading;
{ static void Main() { var sw = Stopwatch.StartNew(); // 100マイクロ秒(0.1ミリ秒)待機 while (sw.ElapsedTicks < (Stopwatch.Frequency / 10000)) // 100マイクロ秒 { // 何もしない } Console.WriteLine("約100マイクロ秒待機しました"); } } |
ただしこの方法はCPUを消費し続けるため、通常の業務アプリケーションでは推奨されません。高精度なタイミング制御が求められる場合は、専用のハードウェアやリアルタイムOSの利用を検討してください。
関連記事
C#超初心者向け始め方ガイド|難易度やおすすめ入門書&学習サイト、Visual Studio設定方法まで
ASP.NET入門|環境構築からWeb開発、ASP.NET Coreとの違いまで解説
4.C# Task.Wait()メソッドの使い方と注意点
C#の待機処理にはTask.Delayメソッド や Thread.Sleepメソッドのほかにも、Task.Waitメソッドも存在します。
Task.Waitメソッドは、非同期処理の完了を同期的に待機するメソッドです。この章では、Task.Waitメソッドの使い方や注意点を紹介します。
Task.Waitメソッドの概要と使い方
Task.Wait()メソッドは、非同期タスクの完了を同期的に待機するためのメソッドです。このメソッドを使用すると、非同期タスクが完了するまで現在のスレッドをブロックします。
Task.Waitメソッドの使い方の例は以下のとおりです。
using System; using System.Threading; using System.Threading.Tasks;
{ public static void Main() { Console.WriteLine("メインスレッド: タスクを開始します");
Task task = Task.Run(() => { Console.WriteLine("別スレッド: 処理を実行中"); Thread.Sleep(3000); // 重い処理をシミュレート Console.WriteLine("別スレッド: 処理が完了"); });
// タスクの完了を待機 task.Wait();
Console.WriteLine("メインスレッド: タスクが完了したので処理を継続します"); } } |
このコード例では、Task.Runで別スレッドでの処理を開始し、task.Wait()を呼び出すことでそのタスクの完了を同期的に待機しています。Wait()メソッドを呼び出したスレッドはその間ブロックされ、タスクが完了すると次の処理に進みます。
Task.Waitメソッドは、結果としてThread.Sleepメソッドと非常に似た動作をします。つまり、現在のスレッドを指定時間ブロックします。
Task.Waitメソッドの注意点
Wait()メソッドを使用する際には、以下の点に注意が必要です。
デッドロック発生リスク:UIスレッドでWait()を呼び出すと、特に非同期処理がUIスレッドに戻る必要がある場合にデッドロックが発生する可能性があります。
リソース消費:同期的な待機は、スレッドリソースを消費し続けます。長時間の待機が必要な場合は、非同期APIを使用する方が効率的です。
例外処理:Wait()メソッドは、待機しているタスクで例外が発生した場合、AggregateExceptionをスローします。適切な例外処理が必要です。
タイムアウト設定の必要性:無限に待機する可能性を避けるため、Wait(timeout)のようにタイムアウト値を設定するとよいでしょう。
特にデッドロックが発生する可能性については注意が必要です。以下のようにUIスレッドでWait()を呼び出すとデッドロックが発生する可能性があります。非同期メソッドが同期コンテキストに戻ろうとしても、そのコンテキストはWait()で既にブロックされているためです。
// デッドロックを引き起こす可能性のあるコード例 private void ButtonClick(object sender, EventArgs e) { // UIスレッドで非同期タスクの完了を同期的に待機(危険) DoSomethingAsync().Wait(); // デッドロックの可能性あり }
{ await Task.Delay(1000); // UIスレッドに戻ろうとする // しかしUIスレッドはWait()でブロックされている } |
UIスレッドで待機したい場合は、非同期処理を使用してデッドロックが発生しないようにするのがおすすめです。
// 推奨される方法 private async void ButtonClick(object sender, EventArgs e) { await DoSomethingAsync(); // デッドロックの心配なし }
{ await Task.Delay(1000); } |
5.まとめ
本記事では、C#で処理を一定時間待機させる方法を紹介しました。
C#で処理を一時停止させる方法としては、Thread.SleepメソッドとTask.Delayメソッドがあります。Thread.Sleepメソッドはスレッドを完全にブロックする同期的な待機で、Task.Delayメソッドはスレッドをブロックしない非同期的な待機です。
コンソールアプリやシンプルな実装にはThread.Sleepも使用可能ですが、UIアプリケーションや複数の非同期処理を含むシステムではTask.Delayを使用するのがおすすめです。
C#での処理待機は、アプリケーションの種類や要件に応じて適切な方法を選択することが重要です。最近では同期的なThread.Sleepよりも非同期的なTask.Delayを使用することが多いです。特にUI操作を伴うアプリケーションでは、応答性を維持するためにもTask.Delayを使用することが推奨されます。
C#の非同期プログラミングは、アプリケーションの応答性とスケーラビリティを向上させるためには欠かせない概念です。適切なメソッドを選択してデッドロックなどの問題を回避することで、効率的で堅牢なアプリケーションを開発できます。
本記事が皆様にとって少しでもお役に立てますと幸いです。
「フリーランスボード」は、数多くのフリーランスエージェントが掲載するITフリーランスエンジニア・ITフリーランス向けの案件・求人を一括検索できるサイトです。
開発環境、職種、単価、稼働形態、稼働日数など様々な条件から、あなたに最適なフリーランス案件・求人を簡単に見つけることができます。
単価アップを目指す方や、自分の得意なスキルを活かせる案件に参画したい方は、ぜひ「フリーランスボード」をご利用ください。
自身に最適なフリーランスエージェントを探したい方はこちらよりご確認いただけます。