การหยุดโปรแกรมชั่วคราวใน C# มี 2 วิธีหลัก: Thread.Sleep (Blocking) และ Task.Delay (Non-blocking/Async)
Thread.Sleep - Blocking Sleep
using System;
using System.Threading;
public class Program
{
public static void Main()
{
Console.WriteLine("Start");
// หยุด 1000 ms = 1 วินาที
Thread.Sleep(1000);
Console.WriteLine("After 1 second");
// Sleep ใน Loop
for (int i = 0; i < 5; i++)
{
Thread.Sleep(500);
Console.WriteLine($"Tick {i + 1}");
}
}
}
Task.Delay - Async Non-blocking Sleep (แนะนำสำหรับ Modern C#)
using System;
using System.Threading.Tasks;
public class Program
{
public static async Task Main()
{
Console.WriteLine("Start");
// Non-blocking - Thread ถูกคืนให้ ThreadPool
await Task.Delay(1000);
Console.WriteLine("After 1 second (Async)");
// ใน Loop Async
for (int i = 0; i < 5; i++)
{
await Task.Delay(500);
Console.WriteLine($"Tick {i + 1}");
}
}
}
เปรียบเทียบ
| ด้าน | Thread.Sleep | Task.Delay |
|---|---|---|
| Blocking | ใช่ (Block Thread) | ไม่ (Yield Control) |
| Async/Await | ไม่รองรับ | รองรับเต็มรูปแบบ |
| Thread Pool | Waste Thread | คืน Thread ให้ Pool |
| Cancellation | ยาก (Thread.Abort - Deprecated) | รองรับ CancellationToken |
| Precision | ~15ms (Windows Default Timer) | ~15ms (เหมือนกัน) |
| ใช้เมื่อ | Console App, Legacy, Background Worker | ASP.NET Core, UI Apps, Modern Async Code |
Task.Delay พร้อม CancellationToken
public async Task DoWorkAsync(CancellationToken cancellationToken)
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Working...");
await Task.Delay(1000, cancellationToken); // หยุดได้ทันทีเมื่อ Cancel
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Cancelled!");
}
}
High-Resolution Timer (Precision < 1ms)
// ใช้ Multimedia Timer (Windows) หรือ SpinWait สำหรับ Micro-delays
using System.Runtime.CompilerServices;
// Busy Wait (Short Delays < 1ms)
public static void MicroDelay(int microseconds)
{
long start = Stopwatch.GetTimestamp();
long frequency = Stopwatch.Frequency;
long target = start + microseconds * frequency / 1_000_000;
while (Stopwatch.GetTimestamp() < target)
{
// SpinWait ยอมให้ CPU ทำงานอื่นได้
Thread.SpinWait(10);
}
}
Thread.Sleep(Timeout.Infinite)
// หยุดนิรันดร์ จนกว่า Thread.Interrupt() หรือ Abort()
// ใช้ใน Background Worker ที่รอ Signal
Thread.Sleep(Timeout.Infinite);
⚠️ ข้อควรระวัง
- อย่าใช้
Thread.Sleepใน UI Thread (WPF/WinForms/MAUI) - จะทำให้ UI Freeze - อย่าใช้ใน ASP.NET Core Request Thread - ทำให้ Scalability ต่ำ
Thread.Sleep(0)= Yield ให้ Thread อื่น (ไม่ใช่ Sleep จริง)- Timer Resolution: Windows Default ~15.6ms, ใช้ `timeBeginPeriod` เพื่อเพิ่ม Precision (แต่กิน Battery)
Summary
// Quick Reference
Thread.Sleep(1000); // Block 1s
await Task.Delay(1000); // Async 1s
await Task.Delay(1000, ct); // Async 1s + Cancellable
Thread.SpinWait(1000); // Busy Wait (CPU Cycles)