在現代軟體開發中,多線程程式設計是提升應用程式效能與回應能力的關鍵技術。C# 作為 .NET 平台的核心語言,提供了豐富且強大的多線程支援機制。本文將系統性地探討 C# 中的多線程核心概念、線程控制、同步與通訊、線程池與定時器,以及互斥對象的應用,並輔以完整的程式碼範例,幫助開發者建立扎實的多線程開發基礎。
作業系統層面的「進程」是資源分配的基本單位,而「線程」則是 CPU 排程執行的基本單位。一個進程可包含多個線程,它們共享進程的記憶體空間(代碼區、堆),但各自擁有獨立的堆疊與暫存器上下文。多線程的優勢在於提高 CPU 利用率:當一個線程因 I/O 或同步等待而阻塞時,CPU 可切換執行其他線程,實現並發處理。
然而,線程並非越多越好。過多線程會帶來記憶體開銷、上下文切換成本、共享資源競爭(需同步機制解決)以及除錯複雜度上升等問題。恰當的類比是:進程如公司,線程如員工。員工太少效率低,太多則管理成本高、內耗嚴重。因此,合理設計線程架構至關重要。
在 C# 中,System.Threading.Thread 類是操作線程的核心。建立線程需提供入口點,透過 ThreadStart 委派指向目標方法:
Thread oThread = new Thread(new ThreadStart(oAlpha.Beta));
oThread.Start();
關鍵控制方法包括:
Start():啟動線程Sleep(ms):靜態方法,讓當前線程休眠指定毫秒數Abort():終止線程(不可恢復,會拋出 ThreadAbortException)Suspend() / Resume():掛起/恢復線程(已過時,不建議使用)Join():阻塞呼叫線程,直到目標線程結束線程狀態由 ThreadState 屬性表示(如 Running、WaitSleepJoin、Aborted 等)。前景線程會阻止進程結束,背景線程則不會;所有前景線程結束時,CLR 會強制終止背景線程。線程優先級(ThreadPriority)可影響 CPU 排程順序,但應謹慎使用,避免飢餓問題。
多線程共享資料時,若缺乏同步會導致競態條件。C# 提供 lock 關鍵字實現互斥區塊:
lock (this) { /* 同一時間僅一線程可進入 */ }
更靈活的 Monitor 類提供物件鎖機制,配合 Wait()、Pulse()、PulseAll() 實現線程間協調通訊。經典的「生產者-消費者」模式展示了如何透過共享緩衝區與狀態旗標,讓生產線程寫入資料後通知消費線程讀取,雙方交替執行:
// 生產者
lock (this) {
while (readerFlag) Monitor.Wait(this);
cellContents = n; readerFlag = true; Monitor.Pulse(this);
}
// 消費者
lock (this) {
while (!readerFlag) Monitor.Wait(this);
Console.WriteLine("Consume: " + cellContents);
readerFlag = false; Monitor.Pulse(this);
}
此模式確保資料不會被重複消費或遺漏,是多線程協作的基石。
頻繁建立/銷毀線程開銷大。ThreadPool 類提供系統管理的線程池,適用於短時執行、大量併發的工作項目:
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), stateObj);
配合 ManualResetEvent 或 AutoResetEvent 等等待控制代碼,可同步等待所有工作項完成。範例中展示了如何佇列多個工作項,並在最後一個項目完成時發出訊號通知主線程。
Timer 類則解決週期性任務需求:
Timer timer = new Timer(callback, state, dueTime, period);
支援動態調整間隔(Change())與釋放資源(Dispose()),適合定時檢查、批次處理等場景。
當多線程間存在複雜依賴關係(如:線程 A 需等待線程 B 和 C 皆完成,線程 D 需等待 B 或 C 任一完成),Mutex 類提供更強大的同步原語:
WaitOne():等待單一 MutexWaitAll():等待陣列中所有 MutexWaitAny():等待陣列中任一 Mutex範例中主線程建立兩個 Mutex,啟動四個工作線程分別以不同等待策略阻塞,主線程按順序釋放 Mutex,精確控制線程啟動順序,最後透過 WaitHandle.WaitAll() 等待所有線程結束。這展示了 Mutex 在協調複雜工作流中的靈活性。
C# 多線程機制從基礎的 Thread 控制,到 lock/Monitor 同步,再到 ThreadPool/Timer 自動化管理,以及 Mutex 進階協調,構建了完整的開發工具箱。實務上應遵循:
ThreadPool 或 Task Parallel Library (TPL) 替代手動管理線程async/await 簡化非同步流程,減少手動同步複雜度掌握這些核心機制,能讓你編寫出高效、穩健、可維護的多線程 C# 應用程式。