| 概念 | 說明 |
|---|---|
| 進程 | 作業系統資源分配單位 (記憶體空間、檔案控制代碼),含至少一個執行緒。 |
| 執行緒 | CPU 排程執行單位,執行程式碼指令。一進程可含多執行緒 (多執行緒)。 |
| 主執行緒 / UI 執行緒 | 進程啟動時建立的第一個執行緒,WinForms/WPF 負責訊息迴圈與 UI 渲染。 |
| 前景執行緒 | 預設建立的執行緒 (`IsBackground=false`),**所有前景執行緒結束前,進程不會退出**。 |
| 背景執行緒 | `IsBackground=true`,**只要所有前景執行緒結束,進程立即終止**,背景執行緒被強制中止 (不執行 finally/finalizer)。 |
using System.Threading;
// 1. 無參數方法
Thread t1 = new Thread(DoWork); // 隱含 ThreadStart 委派
t1.Name = "Worker-1"; // 除錯時顯示於執行緒視窗
t1.IsBackground = true; // 設為背景執行緒
t1.Start();
// 2. 有參數方法 (ParameterizedThreadStart)
Thread t2 = new Thread(obj => DoWorkWithParam((int)obj));
t2.Start(42); // 參數透過 Start 傳入
// 3. 常用控制方法
Thread.Sleep(1000); // 讓出 CPU 1 秒 (毫秒)
t1.Join(); // 等待 t1 結束 (阻塞呼叫執行緒)
t1.Abort(); // 【不推薦】強制終止,易殘留資源、破壞狀態
// 建議:使用 CancellationToken 協作式取消
// 4. 取得目前執行緒
Thread current = Thread.CurrentThread;
UI 控制項具有**執行緒親和性**,僅允許建立它們的執行緒 (UI 執行緒) 存取。背景執行緒直接存取會拋出 `InvalidOperationException`。
// 錯誤示範
textBox1.Text = "從背景執行緒設值"; // 拋出例外
// 正確做法:Invoke / BeginInvoke (WinForms)
if (textBox1.InvokeRequired)
textBox1.Invoke(new Action(() => textBox1.Text = "安全設值"));
else
textBox1.Text = "安全設值";
// WPF 使用 Dispatcher
Application.Current.Dispatcher.Invoke(() => textBox1.Text = "安全設值");
臨時關閉檢查 (僅除錯/測試用):Control.CheckForIllegalCrossThreadCalls = false; **嚴禁生產環境使用**。
int counter = 0;
for (int i = 0; i < 10; i++)
new Thread(() => { for (int j = 0; j < 10000; j++) counter++; }).Start();
// 結果往往 < 100000,因 counter++ 非原子操作 (讀-改-寫)
private readonly object _lockObj = new object();
int counter = 0;
void Increment()
{
lock (_lockObj) // 同一時間僅一執行緒進入
{
for (int i = 0; i < 10000; i++) counter++;
}
}
// 更高效能的原子操作 (適用於單一數值)
System.Threading.Interlocked.Increment(ref counter);
| 類別 | 用途 | 關鍵方法 |
|---|---|---|
Mutex | 跨進程同步 (命名互斥體) | `WaitOne`, `ReleaseMutex` |
Semaphore / SemaphoreSlim | 限制並發存取數量 (資源池) | `Wait`, `Release` |
ReaderWriterLockSlim | 讀多寫少場景,允許多讀單寫 | `EnterReadLock`, `EnterWriteLock` |
AutoResetEvent / ManualResetEvent | 執行緒等待/通知訊號 | `WaitOne`, `Set` |
Barrier | 多執行緒階段同步 (集合點) | `SignalAndWait` |
// Task Parallel Library (TPL) - .NET 4.0+ 推薦
Task.Run(() => DoWork()); // 背景執行緒池執行
Task.Factory.StartNew(() => DoWork(param)); // 進階控制
// async/await - 非同步程式設計核心
await Task.Run(() => DoWorkAsync()); // 不阻塞呼叫執行緒
// Parallel / PLINQ - 資料平行
Parallel.For(0, 100, i => Process(i));
var result = data.AsParallel().Where(x => x.Active).ToList();
理解「進程 vs 執行緒」、「前景 vs 背景」、「同步機制」、「委派本質」是 .NET 多執行緒開發的基石。實務中**拥抱 TPL 與 async/await**,將低層 `Thread`/`lock` 封裝於庫層或基礎設施,專注於業務非同步流程設計,才能寫出高效能、可維護、無死結的並發程式。