Multithreading cho phép chương trình thực hiện nhiều tác vụ đồng thời. Trong C#, lớp System.Threading.Thread quản lý luồng. Luồng đầu tiên chạy Main là Main Thread, các luồng tạo thêm là Worker Threads.
Vòng đời Thread
- Unstarted: Đã new Thread nhưng chưa
Start(). - Running: Đang thực thi.
- WaitSleepJoin:
Sleep(),Wait(),Join(). - Suspended (Legacy):
Suspend()(deprecated). - Stopped/Aborted: Hoàn thành hoặc
Abort()(deprecated).
Ví dụ 1: Tạo và chạy Thread cơ bản
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread mainThread = Thread.CurrentThread;
mainThread.Name = "MainThread";
Console.WriteLine($"Running on: {mainThread.Name} (ID: {mainThread.ManagedThreadId})");
// Tạo child thread
Thread child = new Thread(ChildTask);
child.Name = "WorkerThread";
child.Start(); // Bắt đầu thực thi
Console.WriteLine("Main thread tiếp tục làm việc khác...");
Thread.Sleep(1000); // Giả lập work
Console.WriteLine("Main thread kết thúc.");
}
static void ChildTask()
{
Console.WriteLine($"[{Thread.CurrentThread.Name}] Bắt đầu");
Thread.Sleep(2000); // Giả lập work 2s
Console.WriteLine($"[{Thread.CurrentThread.Name}] Kết thúc");
}
}
Ví dụ 2: Thread với tham số (ParameterizedThreadStart)
using System;
using System.Threading;
class Program
{
static void Main()
{
Thread t = new Thread(PrintNumbers);
t.Start(5); // Truyền object parameter
Thread t2 = new Thread(obj =>
{
int count = (int)obj;
for (int i = 0; i < count; i++)
Console.WriteLine($"Lambda thread: {i}");
});
t2.Start(3);
Console.ReadKey();
}
static void PrintNumbers(object maxObj)
{
int max = (int)maxObj;
for (int i = 0; i < max; i++)
Console.WriteLine($"Thread: {i}");
}
}
Cách hiện đại: Task / Task<T> (TPL - Task Parallel Library)
Khuyến nghị dùng Task thay vì Thread trực tiếp cho hầu hết trường hợp:
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
// Fire-and-forget
Task.Run(() => DoWork("Task 1"));
// With result
Task calcTask = Task.Run(() => Calculate(10));
int result = await calcTask; // Non-blocking wait
Console.WriteLine($"Result: {result}");
// Parallel
await Task.WhenAll(
Task.Run(() => DoWork("A")),
Task.Run(() => DoWork("B"))
);
}
static void DoWork(string name)
{
Thread.Sleep(1000);
Console.WriteLine($"{name} done on thread {Thread.CurrentThread.ManagedThreadId}");
}
static int Calculate(int n) => n * n;
}
So sánh Thread vs Task
| Đặc điểm | Thread | Task (TPL) |
|---|---|---|
| Quản lý | Manual | ThreadPool tự động |
| Return value | Khó (cần shared state) | Task<T> tự nhiên |
| Exception handling | Phức tạp | try/await catch tự nhiên |
| Composition | Khó | WhenAll, WhenAny, ContinueWith |
| Cancellation | Khó (Abort deprecated) | CancellationToken chuẩn |
| Async/await | Không | Hỗ trợ đầy đủ |
Khi nào dùng Thread trực tiếp?
- Cần kiểm soát chi tiết: Priority, IsBackground, ApartmentState (STA/MTA).
- Long-running, dedicated thread (ví dụ: UI message pump, server listener).
- Interop với unmanaged code yêu cầu thread cụ thể.
Tóm lại: Dùng Task.Run, async/await, Parallel.ForEach cho 99% trường hợp. Chỉ dùng Thread khi cần kiểm soát cấp thấp.