標籤: 建材軟體

【軟體開發、系統開發】多執行緒多任務存取相同變數,隔離保留各自任務的值 ThreadLocal 技術講解

      在講解幾篇關於多工、多執行緒、平行作業的技術文章後,想來談談另外一個深入的關鍵多多執行緒的問題,那就是多執行緒(多工)作業模式下,如何存取相同變數值,而且又希望各自的執行緒對相同變數又有各自的“值”。

      在 .Net 技術平台下,有個 ThreadLocal<T> 的泛型類別,這個類別可以專門用於有多個執行緒需要共同存取一個變數,但每個執行緒對這個變數的值,又個別記錄隔離儲存,互不影響。我舉個例子來說明,有執行緒A、執行緒B、執行緒C、執行緒D,這四個執行緒平行作業,將共同存取一個變數 X ,但在執行緒A存取變數X時,設定值為 10;執行緒B存取變數X時,設定值為 20;執行緒C存取變數X時,設定值為 30;執行緒D存取變數X時,設定值為 40; 在執行緒A設定 X變數值為 10時,並不會影響到 執行緒 B/C/D 各自設定的 X 變數值。

     一樣在此,我透過一個程式範例來進行實例說明,這個專案類型就簡單用 Console 控制台類型來引導…

完整程式碼如下:

namespace NetQna.Demo
{
     /// <summary>
     /// ThreadLocal 示範教學(網智數位-軟體開發)
     /// </summary>
     public class Program
     {
         /// <summary>
         /// 所有執行緒共同存取的變數值
         /// </summary>
         static ThreadLocal<int> X = new ThreadLocal<int>();


        static void ExecThreadTask(object obj)
         {
             ThreadEntity currThread = (ThreadEntity)obj;
             //在各自的執行緒環境設定 X 變數值,觀察各自的執行緒下,X 變數值各自記錄
             X.Value = currThread.ThreadValue;


            //顯示出 目前所在的執行緒 的值
             Console.WriteLine($"現在的執行緒 ID:{Thread.CurrentThread.ManagedThreadId},{nameof(X)}變數值為:{X.Value}。");
             //顯示出 目前所在的執行緒 的值
             Console.WriteLine($"現在的執行緒 名稱:{currThread.ThreadName},{nameof(X)}變數值為:{X.Value}。");
             Console.WriteLine();
         }


        static void Main(string[] args)
         {


            Dictionary<string, int> threadABCD = new Dictionary<string, int> { { “A", 10 }, { “B", 20 }, { “C", 30 }, { “D", 40 } };


            //分別啟動 A、B、C、D 執行緒,並執行 存取 X 變數值
             foreach (var t in threadABCD)
             {
                 ThreadEntity obj = new ThreadEntity { ThreadName = t.Key, ThreadValue = t.Value };


                //Action<string, int> action = ExecThreadTask(t.Key, t.Value);
                 Thread currThread = new Thread(ExecThreadTask);
                 currThread.Start(obj);


                //這邊我刻意停頓 1 秒,以利顯示各自執行緒
                 Thread.Sleep(1000);
             }


            Console.Read();


            X.Dispose(); //X 變數 釋放
         }


         public class ThreadEntity
         {
             public string ThreadName { get; set; }
             public int ThreadValue { get; set; }


        }
     }
}

程式說明講解

1

一開始我宣告一個屬性變數為 X ,也就是今天講解主要的類別 ThreadLocal,
待會就是用 這個 X 變數,來讓所有執行緒進行存取設定 X 變數值。


2

宣告一個帶有 object 參數的方法,待會就是要讓所有執行緒去各自執行這個方法,這個方法主要我將  object 型態 的 參數 obj 轉型為我自己宣告的類別 ThreadEntity 類別(PS:因為 Thread 建構子對應的方法的參數只能是 object 型態,所以我透過轉型來避開這限制)。

public class ThreadEntity
{
     public string ThreadName { get; set; }
     public int ThreadValue { get; set; }


}

最關鍵的地方,我在這個方法設定了各自執行緒要對應的 X 變數值

//在各自的執行緒環境設定 X 變數值,觀察各自的執行緒下,X 變數值各自記錄
X.Value = currThread.ThreadValue;

3

我這邊分別建立 A、B、C、D 四個執行緒,然後分別設定他們待會要指定 X 變數的值為(10、20、30、40)。

程式執行結果如下圖
d

可以看出 A、B、C、D執行緒各自維護自己 X 變數的值。


參考文章
C#多工作業與平行處理技術講解
1.透過 Thread 類別撰寫多執行緒多工作業。
2.透過 Delegate 委託支援的方法,撰寫非同步任務。
3-1.透過 Parallel 類別操控多任務平行作業(一)。
3-2. 透過 Parallel 類別操控多任務平行作業(二)。
4.使用 Task 自行控制非同步任務作業。
5.在非同步作業時,如何取消非同步任務。
6.多執行緒多任務存取相同變數,但卻各自隔離保留各自任務的值。
7.非同步存取變數的問題。
8.非同步資源鎖定解決方式。



網智數位-軟體開發(軟件開發)
針對各特殊產業都可以量身定做符合貴公司的需求,別人無法克服的就是我們的挑戰
業務合作、軟體委外開發
業務窗口:allen@netqna.com
聯繫電話:0920-883-870
公司電話:02-55991310
公司地址(業務營運處):台北市中山區錦州街 25 號 5 樓
skype: netqna
line:netqna
微信:netqna
黃先生 Allen