Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Chương trình C# dừng (kill) luồng an toàn

Không nên dùng Thread.Abort() — đã bị deprecated (C#/.NET Core) vì gây rò rỉ tài nguyên, deadlock, hỏng trạng thái shared data. Cách an toàn: dùng cờ (flag) hủy (Cancellation Pattern).

Mô hình dừng an toàn

  • Luồng worker kiểm tra cờ flag (volatile bool) trong vòng lặp.
  • Luồng chính set flag = true để yêu cầu dừng.
  • Luồng worker thoát vòng lặp, kết thúc phương thức → luồng tự chết.
  • Luồng chính gọi thread.Join() chờ worker kết thúc.

Mã nguồn

using System;
using System.Threading;

class Demo {
    static void Main(string[] args) {
        MyClass c = new MyClass();
        
        // Tạo và bắt đầu luồng
        Thread thread = new Thread(c.Display);
        thread.Start();
        
        Console.WriteLine("Nhấn phím bất kỳ để dừng luồng...");
        Console.ReadKey();
        
        // Yêu cầu dừng
        c.Stop();
        
        // Chờ luồng kết thúc
        thread.Join();
        Console.WriteLine("Luồng đã dừng an toàn.");
    }
}

public class MyClass {
    // volatile: đảm bảo đọc/ghi trực tiếp main memory, không cache register
    private volatile bool flag = false;
    
    public void Display() {
        while (!flag) {
            Console.WriteLine("Đang làm việc...");
            Thread.Sleep(2000);
        }
    }
    
    public void Stop() {
        flag = true; // Bật cờ yêu cầu dừng
    }
}

Kết quả

Đang làm việc...
Đang làm việc...
Nhấn phím bất kỳ để dừng luồng...
Luồng đã dừng an toàn.

Cách hiện đại: CancellationToken (khuyên dùng)

using System;
using System.Threading;
using System.Threading.Tasks;

class Program {
    static async Task Main() {
        var cts = new CancellationTokenSource();
        var token = cts.Token;
        
        var task = Task.Run(() => Worker(token), token);
        
        Console.WriteLine("Nhấn Enter để hủy...");
        Console.ReadLine();
        
        cts.Cancel(); // Yêu cầu hủy
        
        try {
            await task; // Chờ task kết thúc (có thể throw OperationCanceledException)
        } catch (OperationCanceledException) {
            Console.WriteLine("Task đã bị hủy.");
        }
    }
    
    static void Worker(CancellationToken token) {
        while (!token.IsCancellationRequested) {
            Console.WriteLine("Working...");
            Thread.Sleep(1000);
            
            // Hoặc: token.ThrowIfCancellationRequested(); // Ném exception khi hủy
        }
        Console.WriteLine("Worker dừng an toàn.");
    }
}

Lưu ý

  • volatile quan trọng cho flag — đảm bảo luồng worker thấy giá trị mới nhất từ luồng chính.
  • CancellationToken là chuẩn .NET hiện đại — hỗ trợ timeout, linked tokens, callback.
  • Luôn dùng Join() hoặc await task để chờ dọn dẹp xong trước khi thoát app.