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

Đa luồng (Multithreading) trong C#

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

  1. Unstarted: Đã new Thread nhưng chưa Start().
  2. Running: Đang thực thi.
  3. WaitSleepJoin: Sleep(), Wait(), Join().
  4. Suspended (Legacy): Suspend() (deprecated).
  5. 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ểmThreadTask (TPL)
Quản lýManualThreadPool tự động
Return valueKhó (cần shared state)Task<T> tự nhiên
Exception handlingPhức tạptry/await catch tự nhiên
CompositionKhóWhenAll, WhenAny, ContinueWith
CancellationKhó (Abort deprecated)CancellationToken chuẩn
Async/awaitKhôngHỗ 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.