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 ý
volatilequan trọng cho flag — đảm bảo luồng worker thấy giá trị mới nhất từ luồng chính.CancellationTokenlà chuẩn .NET hiện đại — hỗ trợ timeout, linked tokens, callback.- Luôn dùng
Join()hoặcawait taskđể chờ dọn dẹp xong trước khi thoát app.