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

C# 多線程基礎入門:進程、線程與多任務核心概念詳解

     編輯:關於C語言

從單任務到多任務的演進

早期作業系統 (如 MS-DOS) 僅支援單任務:同一時間只能執行一個程式。隨著硬體效能提升,引入分時系統:CPU 時間切片輪轉給多個程式,宏觀上呈現「同時執行」的假象——這就是多任務。

進程 vs 線程:核心區別

維度進程線程
定義執行中程式的實例,資源分配單位進程內的執行序列,CPU 調度單位
記憶體空間獨立虛擬位址空間 (4GB/用戶態 2GB)共享進程記憶體 (堆、全域變數、代碼段)
資源擁有擁有檔案控制代碼、通訊埠、安全權杖等僅擁有執行上下文 (暫存器、堆疊、TLS)
建立/銷毀開銷大 (需分配獨立資源)小 (輕量級,共享資源)
通訊方式IPC (管道、共享記憶體、Socket、Remoting)直接讀寫共享記憶體 (需同步)
容錯隔離進程崩潰不影響其他進程線程崩潰導致整個進程終止

線程內部結構

  • 執行指標 (EIP/RIP):下一條指令位址。
  • 暫存器組:通用暫存器、旗標暫存器等。
  • 堆疊:區域變數、呼叫鏈、返回位址、例外處理框架 (每線程獨立,預設 1MB)。
  • 線程本地儲存 (TLS):線程專屬資料槽。
  • 優先級:決定 CPU 時間片分配權重。

線程調度模型

搶佔式多任務

  • OS 強制分配時間片 (Windows/Linux/macOS 現代系統預設)。
  • 時間片用盡 → 強制上下文切換 → 下一就緒線程執行。
  • 優先級高者可打斷低者;同優先級輪轉。
  • 優點:公平、即時響應;缺點:切換開銷、需同步機制保護共享資料。

協作式多任務 (非搶佔)

  • 線程主動釋放 CPU (呼叫 Yield、Sleep、I/O 等待)。
  • 早期 Windows 3.x、Mac OS 9 採用。
  • 風險:惡意/錯誤線程可獨佔 CPU 導致系統假死。

混合模式

高優先級線程搶佔,同優先級協作。現代 OS 核心皆為搶佔式,應用層可透過優先級影響調度。

多核心與真平行

  • 單核心:分時多工 (邏輯並行)。
  • 多核心:物理並行,每核心同時執行一線程。
  • 線程親和性:可綁定線程至特定核心 (ProcessorAffinity),減少快取失效與遷移開銷。

何時需要多線程?

適用場景

  • ✅ UI 響應性:耗時運算/IO 放背景線程,UI 線程專職處理訊息泵。
  • ✅ 並行處理:獨立任務分解 (圖像處理、批次轉碼、並行查詢)。
  • ✅ 伺服器高併發:每請求一線程 (傳統模型) / 非同步 IO + 線程池 (現代模型)。
  • ✅ 異步事件處理:計時器、網路封包到達、硬體中斷。

不適用/謹慎場景

  • ❌ 簡單順序邏輯:增加複雜度無收益。
  • ❌ 高度共享可變狀態:同步開銷超過並行收益。
  • ❌ 線程數過多:上下文切換風暴、記憶體耗盡 (每線程 1MB 堆疊)。

多線程設計原則

  1. 優先級分層:UI/輸入 → Highest;網路偵聽 → AboveNormal;運算/背景 → Normal/BelowNormal。
  2. 最小化共享狀態:傾向不可變物件、ThreadLocal、訊息傳遞 (Channel/BlockingCollection)。
  3. 同步原語選擇:lock (監視器) → SemaphoreSlim (信號量) → ReaderWriterLockSlim (讀多寫少) → Interlocked (原子操作) → Monitor.Wait/Pulse (條件變數)。
  4. 避免死鎖:固定鎖順序、超時嘗試 (Monitor.TryEnter)、減少鎖持有範圍。
  5. 取消與超時:CancellationToken 貫穿異步鏈路,Task.WhenAny 實作超時。

C#/.NET 線程基礎 API 概覽

API用途備註
Thread手動建立/控制線程功能最全,開銷最大,現代少用
ThreadPool短時任務佇列自動調節,QueueUserWorkItem
Task/Task<T>異步操作抽象TAP 模式核心,支援 await/組合
Parallel/PLINQ資料並行自動分割迴圈/查詢
async/await非阻塞異步流程編譯器生成狀態機,現代標準
Timer週期性排程線程池觸發,高精度

經典範例:UI 線程與背景運算分離

// 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 越少,效能越高。

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