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

C# 併發程式設計核心:單執行緒與多執行緒深度對比實戰

     編輯:關於C語言

核心概念速覽

  • 進程 vs 執行緒: 進程是資源分配單位(獨立記憶體空間),執行緒是 CPU 排程單位(共享進程資源)。一個進程可包含多個執行緒。
  • 應用程式域: CLR 邏輯隔離邊界,提供錯誤與安全隔離。單一執行緒啟動,但可建立額外執行緒與應用程式域。
  • 多執行緒優勢: 避免單一阻塞操作凍結整個應用程式,提升回應性與吞吐量。
  • 多執行緒代價: 記憶體開銷、上下文切換成本、共享資源同步複雜度、除錯困難度指數級上升。

實戰對比:WinForms 文字輸出場景

以下範例模擬「逐字元輸出文字並延遲 1 秒」的耗時操作,對比單執行緒阻塞 UI 與多執行緒並行處理的差異。

共用基礎設施

public delegate void WriteTextCallback(char ch); // 跨執行緒更新 UI 的委派

public void Write(string text, WriteTextCallback callback)
{
    foreach (char c in text)
    {
        callback(c); // 呼叫委派更新對應 TextBox
        // 模擬耗時操作:忙碌等待 1 秒(實務請用 Task.Delay)
        DateTime now = DateTime.Now;
        while (now.AddSeconds(1) > DateTime.Now) { }
    }
}

場景一:單執行緒(阻塞 UI)


private void btnStart_Click(object sender, EventArgs e)
{
    // 勾選 CheckBox1 才執行
    if (checkBox1.Checked)
    {
        textBox1.Clear();
        // 直接在 UI 執行緒呼叫 Write,會凍結整個視窗
        Write(textBox3.Text, c => textBox1.AppendText(c.ToString()));
    }
    
    if (checkBox2.Checked)
    {
        textBox2.Clear();
        // 必須等待第一個 Write 完全結束才會執行
        Write(textBox3.Text, c => textBox2.AppendText(c.ToString()));
    }
}

現象: 視窗標題列顯示「未回應」,無法移動、無法點擊其他控制項,兩個 TextBox 依序輸出而非同時。

場景二:多執行緒(並行非阻塞)


private void btnStart_Click(object sender, EventArgs e)
{
    // 允許跨執行緒存取控制項(教學用,生產環境請用 Invoke/BeginInvoke)
    CheckForIllegalCrossThreadCalls = false;

    if (checkBox1.Checked)
    {
        textBox1.Clear();
        var t1 = new Thread(() => Write(textBox3.Text, c => textBox1.AppendText(c.ToString())));
        t1.Start();
    }

    if (checkBox2.Checked)
    {
        textBox2.Clear();
        var t2 = new Thread(() => Write(textBox3.Text, c => textBox2.AppendText(c.ToString())));
        t2.Start();
    }
}

現象: 視窗保持流暢可操作,兩個 TextBox 同時逐字元輸出,互不干擾。

關鍵技術點解析

技術點單執行緒多執行緒
UI 回應性完全凍結完全正常
執行順序嚴格循序並行交錯
資源爭用無需同步機制
程式碼複雜度低中高
適用場景簡單、快速、CPU 密集任務I/O 密集、長時間運算、需保持 UI 回應

現代化改良建議

上述範例使用 Thread 類別與 CheckForIllegalCrossThreadCalls = false 屬於教學示範手法。實際專案建議採用:

  • Task / async-await: await Task.Run(() => DoWork()) 自動處理執行緒池排程與上下文捕捉。
  • Progress / IProgress: 安全回報進度至 UI 執行緒,無需手動 Invoke。
  • CancellationToken: 統一取消機制,避免 Thread.Abort() 等危險作法。
  • Channel / Dataflow: 生產者-消費者模式的無鎖高效替代方案。

總結

多執行緒是把雙面刃:用得好能讓應用程式「動起來」,用不好會引入難以重現的競態條件與死結。建議遵循「預設單執行緒、證明需要時再並行」原則,優先使用高階抽象而非手動操作 Thread。

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