Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C#

ทำให้โปรแกรม C# หยุดพัก (Sleep) ด้วย Thread.Sleep และ Task.Delay

การหยุดโปรแกรมชั่วคราวใน 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.SleepTask.Delay
Blockingใช่ (Block Thread)ไม่ (Yield Control)
Async/Awaitไม่รองรับรองรับเต็มรูปแบบ
Thread PoolWaste Threadคืน Thread ให้ Pool
Cancellationยาก (Thread.Abort - Deprecated)รองรับ CancellationToken
Precision~15ms (Windows Default Timer)~15ms (เหมือนกัน)
ใช้เมื่อConsole App, Legacy, Background WorkerASP.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)