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 = ; i < ; i++)
{
Thread.Sleep(); 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 = ; i < ; i++)
{
Thread.Sleep(); 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(); 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();,它们分别能阻止传播和重置传播,默认是允许传播的。
C# 线程本地存储 调用上下文 逻辑调用上下文的更多相关文章
- .NET:线程本地存储、调用上下文、逻辑调用上下文
.NET:线程本地存储.调用上下文.逻辑调用上下文 目录 背景线程本地存储调用上下文逻辑调用上下文备注 背景返回目录 在多线程环境,如果需要将实例的生命周期控制在某个操作的执行期间,该如何设计?经典的 ...
- 线程本地存储 ThreadLocal
线程本地存储 · 语雀 (yuque.com) 线程本地存储提供了线程内存储变量的能力,这些变量是线程私有的. 线程本地存储一般用在跨类.跨方法的传递一些值. 线程本地存储也是解决特定场景下线程安全问 ...
- 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理
原文链接地址:http://www.cppblog.com/Tim/archive/2012/07/04/181018.html 本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们 ...
- 线程本地存储TLS(Thread Local Storage)的原理和实现——分类和原理
本文为线程本地存储TLS系列之分类和原理. 一.TLS简述和分类 我们知道在一个进程中,所有线程是共享同一个地址空间的.所以,如果一个变量是全局的或者是静态的,那么所有线程访问的是同一份,如果某一个线 ...
- ThreadLocal(线程本地存储)
1. ThreadLocal,即线程本地变量或线程本地存储. threadlocal的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或组件之间一些公共变量传递的 ...
- 线程本地存储(动态TLS和静态TLS)
线程本地存储(TLS) 对于多线程应用程序,如果线程过于依赖全局变量和静态局部变量就会产生线程安全问题.也就是一个线程的使用全局变量可能会影响到其他也使用此全局变量的线程,有可能会造成一定的错误,这可 ...
- Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic
Atitit usrqbg1821 Tls 线程本地存储(ThreadLocal Storage 规范标准化草案解决方案ThreadStatic 1.1. ThreadLocal 设计模式1 1.2. ...
- 线程本地存储(Thread Local Storage, TLS)简单分析与使用
在多线程编程中, 同一个变量, 如果要让多个线程共享访问, 那么这个变量可以使用关键字volatile进行声明; 那么如果一个变量不想使多个线程共享访问, 那么该怎么办呢? 呵呵, 这个办法就是TLS ...
- Java线程本地存储ThreadLocal
前言 ThreadLocal 是一种 无同步 的线程安全实现 体现了 Thread-Specific Storage 模式:即使只有一个入口,内部也会为每个线程分配特有的存储空间,线程间 没有共享资源 ...
随机推荐
- POJ - 1426 Find The Multiple(搜索+数论)
转载自:優YoU http://user.qzone.qq.com/289065406/blog/1303946967 以下内容属于以上这位dalao http://poj.org/problem? ...
- git回滚远程仓库代码/错提master分支的恢复
前言 今天周五了,刚接了个新微服务模块,下班前高高兴兴开发完,提交git代码,jenkins发布到测试环境.突然看到一个提示 我最近提的代码呢?!! 想到可能会提错仓库,转念一想,不对呀,我怎有这么高 ...
- DotNetBar TextBoxDropDown响应按键事件
textBoxDropDownHelp.TextBox.KeyDown += new KeyEventHandler(textBoxDropDownHelp_KeyDown); private voi ...
- MyBatis向数据库中批量插入数据
Foreach标签 foreach: collection:指定要遍历的集合; 表示传入过来的参数的数据类型.该参数为必选.要做 foreach 的对象,作为入参时,List 对象默认用 list 代 ...
- luogu 1006 传纸条
三/四维dp,将两次传递均看作从左上而来,在dp过程中注意防止越界/重合 f[i][j][k][l]直接枚举两轮的点,如下 #include<bits/stdc++.h> #define ...
- Python中str()和repr()函数的区别
在 Python 中要将某一类型的变量或者常量转换为字符串对象通常有两种方法,即 str() 或者 repr() . 区别与使用函数str() 用于将值转化为适于人阅读的形式,而repr() 转化为供 ...
- Java垃圾回收机制复习
一.如何确定某个对象是“垃圾” 二.典型的垃圾收集算法 三.典型的垃圾收集器 JVM(HotSpot) 7种垃圾收集器的特点及使用场景 https://www.cnblogs.com/chengxuy ...
- tidb 架构 ~Tidb学习系列(3)
tidb集群安装测试1 环境 3台机器2 配置 server1 pd服务+tidb-server server2 tidb-kv server3 tidb-kv3 环境配置命令 ser ...
- qt无法使用终端启动的解决方法
在Terminal中直接输入命令就能打开QtCreator, i.e. ~$ qtcreator 就可以打开Qt Creator了. 想完成这个功能的原因是,一般在Linux下打命令比较方便,而师兄给 ...
- 关注网页的更新状况,了解最新的handsup 消息.
// 第一部分是网页截图和源码保存 // upon page load. var fs = require("fs"); var resourceWait = 300, maxRe ...