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 模式:即使只有一个入口,内部也会为每个线程分配特有的存储空间,线程间 没有共享资源 ...
随机推荐
- Java高并发秒杀API之高并发优化
---恢复内容开始--- 第1章 秒杀系统高并发优化分析 1.为什么要单独获得系统时间 访问cdn这些静态资源不用请求系统服务器 而CDN上没有系统时间,需要单独获取,获取系统时间不用优化,只是n ...
- 006、容器 What、Why、How(2018-12-21 周五)
参考https://www.cnblogs.com/CloudMan6/p/6751516.html What - 什么是容器? 容器是一种轻量级.可移植.自包含的软件打包技术,是应用 ...
- VxWorks Fuzzing 之道:VxWorks 工控实时操作系统漏洞挖掘调试与利用揭秘
转载:freebuf 0×00 前言 关于VxWorks,这里引用44CON议题<攻击 VxWorks:从石器时代到星际>探究 一文章中的介绍: VxWorks 是世界上使用最广泛的一种在 ...
- golang string int int64转换
#string到int int,err:=strconv.Atoi(string) #string到int64 int64, err := strconv.ParseInt(string, 10, 6 ...
- 字典取KEY,占位符,延迟刷新
flash 监听事件者 与 事件发出者 比如说现在有A和B,A.addChild(B)A监听鼠标点击事件那么当点击B时,target是B,currentTarget是A也就是说,currentTarg ...
- 第15月第6天 ios UIScrollView不能响应TouchesBegin
1. 1:@property MyScrollView *scrollView; 2:给MyScrollView,增加类别:MyScrollView+Touch 3:在类别里实现下面三个方法: @im ...
- day2 查看文件目录命令:ls
查看当前文件夹下面多有的目录文件ls 查看当前目录下面所有的文件,包括隐藏的文件ls -a(或者两个一样ls -all) 显示除"."和".."外的所有文件ls ...
- 11、Logback日志框架介绍和SpringBoot整合实战 2节课
1.新日志框架LogBack介绍 简介:日志介绍和新日志框架Logback讲解 1.常用处理java的日志组件 slf4j,log4j,logback,common-logging 等 ...
- 矩阵的SVD分解
转自 http://blog.csdn.net/zhongkejingwang/article/details/43053513(实在受不了CSDN的广告) 在网上看到有很多文章介绍SVD的,讲的也都 ...
- 【转】Python之装饰器
[转]Python之装饰器 本节内容 必要知识回顾 情景模拟 装饰器的概念及实现原理 回马枪(带参数的装饰器) 一. 必要知识回顾 在开始说装饰器之前,需要大家熟悉之前说过的相关知识点: 函数即“变量 ...