LocalDataStoreSlot VS CallContext

本文详细介绍了线程槽(LocalDataStoreSlot)和CallContext在C#中的使用方法,通过示例展示了如何在多线程环境下进行线程特定数据的存储与获取,特别强调了CallContext在保持请求上下文信息上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



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); 
        }
答案结果就是对的了。
谢谢分享!
 
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值