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

C# 多執行緒傳遞參數解決方案:避免撰寫大量重複方法

     編輯:關於C#

開發多執行緒應用時,ThreadStart 委派不支援參數傳遞是常見痛點。當有大量相似執行緒(如 100 個連線掃描)僅參數不同時,若為每個執行緒寫獨立方法,程式碼將極度膨脹。本文提供一個以共用欄位暫存參數的實用解決方案。

核心問題

// ThreadStart 無參數簽名
public delegate void ThreadStart();

// 導致必須寫大量重複方法
void ThreadMethod1() { /* 參數 A */ }
void ThreadMethod2() { /* 參數 B */ }
// ... 100 個方法?

解決方案:類別欄位暫存 + 執行緒啟動同步

實作範例

public class PortScanner
{
    private ServerBean _sharedParameter; // 類別層級暫存參數
    private const int MAX_SERVERS = 100;
    private ServerState[] _serverStates;

    public void StartScanning()
    {
        for (int i = 0; i < MAX_SERVERS; i++)
        {
            // 1. 先將參數寫入共用欄位
            _sharedParameter = (ServerBean)_serverStates[i];

            // 2. 建立並啟動執行緒
            var thread = new Thread(ScanPort);
            thread.Start();

            // 3. 關鍵:短暫睡眠確保執行緒讀取到參數
            Thread.Sleep(10); 
        }
    }

    private void ScanPort()
    {
        // 執行緒進入點第一件事:複製參數到區域變數
        var myParam = _sharedParameter;
        
        // 後續使用 myParam 執行邏輯
        // ...
    }
}

原理分析

  1. 共用欄位作為參數傳遞的「信箱」
  2. 執行緒啟動後立即複製參數到區域變數,避免後續迴圈覆寫
  3. Thread.Sleep(10) 給予新執行緒足夠時間完成複製(非精確同步,但實務上通常足夠)

⚠️ 潛在風險與改進方向

風險說明改進方案
競態條件 Sleep 時間不夠導致參數被覆寫 使用 ParameterizedThreadStart + thread.Start(param)(.NET 2.0+ 內建支援)
記憶體可見性 多核心環境下欄位讀取可能不一致 加上 volatile 關鍵字或使用 Interlocked
例外處理 執行緒內未捕獲例外會終止進程 在 ScanPort 內包裹 try-catch 並記錄日誌

現代最佳實踐(.NET 4.0+)

// 使用 ParameterizedThreadStart(.NET 2.0 即支援)
var thread = new Thread(state => 
{
    var param = (ServerBean)state;
    ScanPort(param);
});
thread.Start(serverBean);

// 或使用 Task + Lambda(.NET 4.0+ 推薦)
Task.Run(() => ScanPort(serverBean));

// 並行處理大量工作
Parallel.ForEach(serverBeans, bean => ScanPort(bean));

總結:共用欄位方案在舊版 .NET 或特殊限制下可用,但現代開發應優先使用 ParameterizedThreadStart、Task 或 Parallel 等內建機制,更安全、簡潔且效能更佳。

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