C# 线程本地存储 调用上下文 逻辑调用上下文
2017-01-19 17:29
399 查看
线程本地存储
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(); 和 ExecutionContext.RestoreFlow();,它们分别能阻止传播和重置传播,默认是允许传播的。
相关文章推荐
- .NET:线程本地存储、调用上下文、逻辑调用上下文
- .NET:线程本地存储、调用上下文、逻辑调用上下文
- [并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)调用复制文件接口的案例]
- NET(C#):线程本地存储(Thread-Local Storage)之ThreadStatic, LocalDataStoreSlot和ThreadLocal<T>
- C#线程本地存储:LocalDataStoreSlot和ThreadLocal<T>
- [并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)调用复制文件接口的案例]
- 线程本地存储(Thread Local Storage, TLS)
- c#中使用call调用oracle存储过程并获取out参数值
- C#调用存储过程简单完整例子
- c#对调用存储过程的简化
- .net C# 跨越线程调用窗体上的控件一个完整的例子
- mysql存储过程及c#调用标准版
- C#调用存储过程简单完整例子
- 使用c#调用oracle存储过程获取存储过程参数信息
- C#调用存储过程
- C#调用存储过程简单完整例子
- 在C#中调用存储过程中的两种返回值
- .Net/C# 应用程序直接读取本地 Cookies 文件 (由于 WinXP SP2 调用 API: InternetGetCookie 无果)
- C#调用存储过程简单完整例子
- C#跨线程窗口调用