早期作業系統 (如 MS-DOS) 僅支援單任務:同一時間只能執行一個程式。隨著硬體效能提升,引入分時系統:CPU 時間切片輪轉給多個程式,宏觀上呈現「同時執行」的假象——這就是多任務。
| 維度 | 進程 | 線程 |
|---|---|---|
| 定義 | 執行中程式的實例,資源分配單位 | 進程內的執行序列,CPU 調度單位 |
| 記憶體空間 | 獨立虛擬位址空間 (4GB/用戶態 2GB) | 共享進程記憶體 (堆、全域變數、代碼段) |
| 資源擁有 | 擁有檔案控制代碼、通訊埠、安全權杖等 | 僅擁有執行上下文 (暫存器、堆疊、TLS) |
| 建立/銷毀開銷 | 大 (需分配獨立資源) | 小 (輕量級,共享資源) |
| 通訊方式 | IPC (管道、共享記憶體、Socket、Remoting) | 直接讀寫共享記憶體 (需同步) |
| 容錯隔離 | 進程崩潰不影響其他進程 | 線程崩潰導致整個進程終止 |
Yield、Sleep、I/O 等待)。高優先級線程搶佔,同優先級協作。現代 OS 核心皆為搶佔式,應用層可透過優先級影響調度。
ProcessorAffinity),減少快取失效與遷移開銷。lock (監視器) → SemaphoreSlim (信號量) → ReaderWriterLockSlim (讀多寫少) → Interlocked (原子操作) → Monitor.Wait/Pulse (條件變數)。Monitor.TryEnter)、減少鎖持有範圍。CancellationToken 貫穿異步鏈路,Task.WhenAny 實作超時。| API | 用途 | 備註 |
|---|---|---|
Thread | 手動建立/控制線程 | 功能最全,開銷最大,現代少用 |
ThreadPool | 短時任務佇列 | 自動調節,QueueUserWorkItem |
Task/Task<T> | 異步操作抽象 | TAP 模式核心,支援 await/組合 |
Parallel/PLINQ | 資料並行 | 自動分割迴圈/查詢 |
async/await | 非阻塞異步流程 | 編譯器生成狀態機,現代標準 |
Timer | 週期性排程 | 線程池觸發,高精度 |
// WinForms/WPF 應用
private async void btnCalculate_Click(object sender, EventArgs e)
{
btnCalculate.Enabled = false;
progressBar.Visible = true;
try
{
// 耗時運算卸載至線程池,不阻塞 UI
var result = await Task.Run(() => HeavyCompute(progress =>
{
// 進度回報需切回 UI 線程
this.Invoke(() => progressBar.Value = progress);
}));
txtResult.Text = result;
}
catch (Exception ex)
{
MessageBox.Show($"Error: {ex.Message}");
}
finally
{
btnCalculate.Enabled = true;
progressBar.Visible = false;
}
}
理解進程與線程的本質差異、調度機制、共享記憶體模型,是編寫正確、高效多線程程式的基石。現代 .NET 開發應優先採用 Task/async/await、ThreadPool、Parallel 等高階抽象,僅在極少數需要精確控制線程生命週期、親和性或 STA 時直接操作 Thread 類別。核心哲學:共享越少,同步越少,Bug 越少,效能越高。