首页 > 代码库 > C# 线程本地存储 调用上下文 逻辑调用上下文
C# 线程本地存储 调用上下文 逻辑调用上下文
线程本地存储
using System;using System.Threading;using System.Threading.Tasks;namespace ConsoleAppTest{ class Program { static void Main(string[] args) { ThreadDataSlotTest.Test(); } } /// <summary> /// 线程本地存储 /// </summary> class ThreadDataSlotTest { public static void Test() { for (var i = 0; i < 10; i++) { Thread.Sleep(10); Task.Run(() => { var slot = Thread.GetNamedDataSlot("test"); if (slot == null) { Thread.AllocateNamedDataSlot("test"); } if (Thread.GetData(slot) == null) { Thread.SetData(slot, DateTime.Now.Millisecond); } Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + Thread.GetData(slot)); }); } Console.ReadLine(); } }}
如果使用了线程池,最好不要使用这种存储机制了,因为线程池可能不会释放使用过的线程,导致多次执行之间可能共享数据(可以每次执行前重置线程本地存储的数据)。
调用上下文
using System;using System.Runtime.Remoting.Messaging;using System.Threading;using System.Threading.Tasks;namespace ConsoleAppTest{ class Program { static void Main(string[] args) { CallContextTest.Test(); } } /// <summary> /// 调用上下文 /// </summary> class CallContextTest { public static void Test() { if (CallContext.GetData("test") == null) { CallContext.SetData("test", "CallContext.SetData"); } for (var i = 0; i < 10; i++) { Thread.Sleep(10); Task.Run(() => { if (CallContext.GetData("test") == null) { CallContext.SetData("test", DateTime.Now.Millisecond); } Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.GetData("test")); }); } Console.ReadLine(); } }}
由上图可以知道,每次执行的数据是完全隔离的,非常符合我们的期望。但是,如果我们期望调用期间又开启了一个子线程,如何让子线程访问父线程的数据呢?这就需要使用到:“逻辑调用上下文”。
逻辑调用上下文
using System;using System.Runtime.Remoting.Messaging;using System.Threading;using System.Threading.Tasks;namespace ConsoleAppTest{ class Program { static void Main(string[] args) { ExecutionContextTest.Test(); } } /// <summary> /// 调用上下文 /// </summary> class ExecutionContextTest { public static void Test() { Console.WriteLine("测试:CallContext.SetData"); Task.Run(() => { CallContext.SetData("test", "wolf"); Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.GetData("test")); Task.Run(() => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.GetData("test")); }); }); Thread.Sleep(100); Console.WriteLine("测试:CallContext.LogicalSetData"); Task.Run(() => { CallContext.LogicalSetData("test", "wolf"); Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.LogicalGetData("test")); Task.Run(() => { Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ":" + CallContext.LogicalGetData("test")); }); ExecutionContext.SuppressFlow(); Task.Run(() => { Console.WriteLine("SuppressFlow 之后:" + CallContext.LogicalGetData("test")); }); ExecutionContext.RestoreFlow(); Task.Run(() => { Console.WriteLine("RestoreFlow 之后:" + CallContext.LogicalGetData("test")); }); }); Console.ReadLine(); } }}
注意 ExecutionContext.SuppressFlow(); 和 xecutionContext.RestoreFlow();,它们分别能阻止传播和重置传播,默认是允许传播的。
C# 线程本地存储 调用上下文 逻辑调用上下文
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。