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