LocalDataStoreSlot VS CallContext



LocalDataStoreSlot 表示線程槽,封裝內存槽以存儲本地數據(MSDN)

.NET Framework 提供了兩個使用線程本地存儲區 (TLS) 的機制:線程相關的靜態字段和數據槽。

  • 線程相關的靜態字段是用 ThreadStaticAttribute 特性標記的 static 字段(Visual Basic 中的 Shared 字段)。 這些字段提供的性能比數據槽的性能好,而且它還啓用了編譯時類型檢查。

  • 與線程相關的靜態字段相比,數據槽性能較低,並且比較難使用。 此外,數據被存儲爲 Object 類型,因此在使用之前必須將其強制轉換爲正確的類型。 但是,如果在編譯時所具有的信息不足以分配靜態字段,則可以使用數據槽。 

LocalDataStoreSlot 結構可用作本地存儲內存機制,線程和上下文可以使用此機制分別存儲線程特定的數據和上下文特定的數據。 公共語言運行時在創建每個進程時給它分配一個多槽數據存儲區數組。 線程或上下文調用各種函數在數據存儲區中分配數據槽、在槽內存儲和檢索數據值、以及釋放數據槽以便在線程或上下文過期後重新使用它。

實例如下:

        static void Main(string[] args)
        {
            for (int num = 0; num < 10; num++)
            {
                Thread thread = new Thread(FatherThread);
                thread.Start(num);
            }

            Console.ReadKey();
        }

        /// <summary>
        /// the method for the father thread.
        /// </summary>
        public static void FatherThread(object num)
        {
            name = num + Thread.CurrentThread.ToString();

            LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("slot"); 
             //設置TLS中的值  
            Thread.SetData(slot, name);  
            Thread threadChild = new Thread(ChildThread);
            threadChild.Start(num);
        }
        public static void ChildThread(object num)
        {
             LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("slot"); 
             string value =  Thread.GetData(slot).ToString();  
             Console.WriteLine(value);
        }
我們會發現結果是空的,大家都應該明白這是因爲子線程的原因。父線程中的本地數據不能夠傳到子線程中,如果是聲明爲全局變量,這樣就違背了初衷。
仔細想想,我們在開發web的項目過程中,經常會用到的HttpContext,這是一個貫穿整個request的上下文數據。其實它的內部實現機制就是我們現在的CallContext.
以下的引文:
CallContext could be persisted throughout the request until it ends while ThreadStatic may or may not work since the request may switch threads.
將上面的代碼修改如下:
static void Main(string[] args)
        {
            for (int num = 0; num < 10; num++)
            {
                Thread thread = new Thread(FatherThread);
                thread.Start(num);
            }

            Console.ReadKey();
        }
 /// <summary>
        /// the method for the father thread.
        /// </summary>
        public static void FatherThread(object num)
        {
            name = num + Thread.CurrentThread.ToString();
            SetName(num.ToString(),name);
            Thread threadChild = new Thread(ChildThread);
            threadChild.Start(num);
        }
public static void ChildThread(object num)
        {
            Console.WriteLine(GetName(num.ToString()));
        }
 public static string GetName(string name)
        {
            return CallContext.LogicalGetData(name).ToString();
        }
        public static void SetName(string name,string value)
        {
            CallContext.LogicalSetData(name, value); 
        }
答案結果就是對的了。
謝謝分享!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章