首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

.NET 多執行緒程式設計實戰總結:前景/背景執行緒、同步鎖、委派本質

     編輯:ASP.NET 基礎

核心概念速覽

概念說明
進程作業系統資源分配單位 (記憶體空間、檔案控制代碼),含至少一個執行緒。
執行緒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 控制項 (WinForms/WPF)

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++ 非原子操作 (讀-改-寫)

解決方案:lock (Monitor) 互斥鎖

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`

執行緒本質:委派包裝

  • `Thread` 建構子接受 **`ThreadStart` (無參) 或 `ParameterizedThreadStart` (單一 object 參數)** 委派。
  • 本質上,執行緒啟動後呼叫委派指向的方法。
  • 現代開發**極少直接操作 `Thread`**,改用:
// 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();

最佳實務檢核表

  1. **預設使用 `Task.Run` / `async/await`**,避免手動管理 `Thread`。
  2. **共享狀態最小化**:傾向不可變物件、區域變數、無鎖資料結構 (`ConcurrentDictionary` 等)。
  3. **鎖粒度最小化**:`lock` 區塊內只做必要邏輯,避免 I/O、長時間運算。
  4. **避免 `Thread.Abort` / `Suspend` / `Resume`**:已過時、不安全。
  5. **取消模式統一用 `CancellationToken`**:`token.ThrowIfCancellationRequested()`。
  6. **異常處理**:`Task` 異常需 `await` 或 `.Wait()` 觀察,否則會成為 `UnobservedTaskException`。
  7. **UI 回報進度**:`IProgress` + `Progress` 自動切換至 UI 執行緒。

結語

理解「進程 vs 執行緒」、「前景 vs 背景」、「同步機制」、「委派本質」是 .NET 多執行緒開發的基石。實務中**拥抱 TPL 與 async/await**,將低層 `Thread`/`lock` 封裝於庫層或基礎設施,專注於業務非同步流程設計,才能寫出高效能、可維護、無死結的並發程式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved