多线程上下文切换 多线程下的调用上下文 : CallContext


多线程上下文切换 多线程下的调用上下文 : CallContext

文章插图
| 总结/Edison Zhou
最近在分析现在团队的项目代码(基于.NET Framework 4.5) , 经常发现一个CallContext的调用 , 记得多年前的时候用到了它 , 但是印象已经不深刻了 , 于是现在来复习一下 。
1 CallContext是个啥?
如果说 , 一个对象保证全局唯一 , 大家肯定会想到一个经典的设计模式:单例模式 。但是 , 如果要使用的对象必须是线程内唯一的呢?
在.NET Framework中 , Microsoft给我们设计了一个CallContext类 。
命名空间:System.Runtime.Remoting.Messaging类型完全限定名称:System.Runtime.Remoting.Messaging.CallContextCallContext类似于方法调用的线程本地存储区的专用集合对象 , 并提供对每个逻辑执行线程都唯一的数据槽 。数据槽不在其他逻辑线程上的调用上下文之间共享 。当 CallContext 沿执行代码路径往返传播并且由该路径中的各个对象检查时 , 可将对象添加到其中 。
简而言之 , CallContext提供线程(多线程/单线程)代码执行路径中数据传递的能力 。
方法
描述
线程安全
SetData
存储给定的对象并将其与指定名称关联 。

GetData
从System.Runtime.Remoting.Messaging.CallContext中检索具有指定名称的对象

LogicalSetData
将给定的对象存储在逻辑调用上下文 , 并将其与指定名称关联 。

LogicalGetData
从逻辑调用上下文中检索具有指定名称的对象 。

FreeNamedDataSlot
清空具有指定名称的数据槽 。

HostContext
获取或设置与当前线程相关联的主机上下文 。在Web环境下等于System.Web.HttpContext.Current
2 探究CallContext方法
上面介绍了CallContext提供的核心方法 , 下面我们就来通过实践来理解一下 。
准备工作
这里准备一个User类作为数据传递对象:
public class User{public string Id { get; set; }public string Name { get; set; }}测试1:GetData、SetData 与 FreeNamedDataSlot
测试代码很简单 , 就是在主线程 和 子线程之中分别传递User对象实例 , 看看最后的效果 。
public void TestGetSetData(){// 主线程执行Console.WriteLine($"Current ThreadId={Thread.CurrentThread.ManagedThreadId}");var user = new User(){Id = DateTime.Now.ToString(),Name = "Edison"};CallContext.SetData("key", user);var value1 = CallContext.GetData("key");Console.WriteLine(user == value1);// 异步线程执行Task.Run(() =>{Console.WriteLine($"Current ThreadId={Thread.CurrentThread.ManagedThreadId}");var value2 = CallContext.GetData("key");Console.WriteLine(value2 == null ?"NULL" : (value2 == value1).ToString());});// 主线程执行Console.WriteLine($"Current ThreadId={Thread.CurrentThread.ManagedThreadId}");value1 = CallContext.GetData("key");Console.WriteLine(value1 == user);// 清理数据槽CallContext.FreeNamedDataSlot("key");var value3 = CallContext.GetData("key");Console.WriteLine(value3 == null ?"NULL" : (value3 == value1).ToString());}上面示例代码的运行结果如下图所示:
多线程上下文切换 多线程下的调用上下文 : CallContext

文章插图
根据上图所示的结果 , 基本可以得出以下两个结论:
1、GetData、SetData方法只能用于单线程环境 , 如果发生了线程切换 , 存储的数据也会随之丢失 。


以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: