浅析C#中的AsnycLocal与ThreadLocal
作者:沉默的雪糕 发布时间:2023-04-18 05:42:31
AsnyncLocal与ThreadLocal都是存储线程上下文的变量,但是,在实际使用过程中两者又有区别主要的表现在:
AsyncLocal变量可以在父子线程中传递,创建子线程时父线程会将自己的AsyncLocal类型的上下文变量赋值到子线程中,但是,当子线程改变线程上下文中AsnycLocal变量值后,父线程不会同步改变。也就是说AsnycLocal变量只会影响他的子线程,不会影响他的父级线程。
TreadLocal只是当前线程的上下文变量,不能在父子线程间同步。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace await_aysnc
{
class Program
{
static ThreadLocal<int> ThreadObj = new ThreadLocal<int>();
static AsyncLocal<int> AsyncObj = new AsyncLocal<int>();
static void Main(string[] args)
{
AsyncObj.Value = 1;
ThreadObj.Value = 1;
Console.WriteLine($"Task执行前:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
Task.Run(async() =>
{
Console.WriteLine($"RunAsync异步执行前:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
await RunAsync();
Console.WriteLine($"RunAsync异步执行后:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
});
Console.WriteLine($"Task执行后:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
Console.Read();
}
static async Task RunAsync()
{
Console.WriteLine($"Delay异步执行前:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId} ");
AsyncObj.Value = 2;
ThreadObj.Value = 2;
await Task.Delay(100);
Console.WriteLine($"Delay异步执行后:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
}
}
}
Task执行前:AsyncObj= 1 ThreadObj= 1 ThreeadId = 1
Task执行后:AsyncObj= 1 ThreadObj= 1 ThreeadId = 1
RunAsync异步执行前:AsyncObj= 1 ThreadObj= 0 ThreeadId = 3
Delay异步执行前:AsyncObj = 1 ThreadObj= 0 ThreeadId = 3
Delay异步执行后:AsyncObj = 2 ThreadObj= 0 ThreeadId = 4
RunAsync异步执行后:AsyncObj = 1 ThreadObj= 0 ThreeadId = 4
从结果上可以看出一下结论:
RunAsync执行前ThreadLocal值被切成0即ThreadLocal变量在新线程里面没有继承主线程的上下文变量,但是AsyncLocal继承了。
Delay返回后,线程id变了,同时,TheadLocal中的变量为0。
RunAsync结束后AyncLocal又切回主线程的上下文值,,同样Threadlocal中的值丢失。
由于await执行完返回之后,.net会在线程池中随机选取一个线程来执行await之后的逻辑,所以,await之后同时也会有一定几率获取到之前的线程,如果出现这种情形,TreadLocal会获取到之前的上下文,此时会出现意料之外的问题,从现象上看报错可能会是一个概率性问题。
来源:https://www.cnblogs.com/liyong-blackStone/p/10270526.html


猜你喜欢
- 一、概述我们对于这个图片肯定会非常熟悉,这两幅图片我们都可以看做是一个文件结构,对于这样的结构我们称之为树形结构。在数据结构中我们了解到可以
- 1.JSON数据交互1.1 JSON概述JSON 是一种轻量级的数据交换格式,是一种理想的数据交互语言,它易于阅读和编写,同时也易于机器解析
- 优麒麟Ubuntu20.04中使用VS Code。VS Code的版本是1.48.0。以下内容仅限于上述环境,对于Windows环境下的使用
- 本文实例为大家分享了Java中Stream流去除List重复元素的具体代码,供大家参考,具体内容如下业务场景在开发中我们常常需要过滤List
- 0. Iochttps://docs.spring.io/spring-framework/docs/current/spring-fram
- 本文实例讲述了C# TreeView无限目录树实现方法。分享给大家供大家参考,具体如下:#region 绑定客户树protected voi
- 1.查找数据库中表的列名<pre name="code" class="html">St
- 目录前言简单示例基础操作定时取消关联取消判断取消源码探究构造入手小插曲WaitHandle注册操作取消操作Cancel操作CancelAft
- 如何在WinForm中请求发送HTTP手工发送HTTP请求主要是调用 System.Net的HttpWebResponse方法手工发送HTT
- SpringMVC * path路径的坑SpringMVC提供了很方便的 * 供我们开发使用。在配置文件中通过<mvc:mapping
- 本文简单介绍如何动态创建接口interface的实现实例对象,包含两个知识点:1.如何获取接口interface的所有实现实例对象?2.如何
- (未给Fragment的布局设置BackGound)之前关于Android中Fragment的概念以及创建方式,我专门写了一篇博文《详解An
- 今天写Tab的时候由于TAB的跳转问题去查资料,倒反而发现更有趣的问题,就是如何将TAB放置在屏幕的底端。 <?xml version
- 下标到指针之间和转换以下的程序做了什么。#include <stdio.h> int main() { int a
- 分布式项目和传统项目的区别就是,分布式项目有多个服务,每一个服务仅仅只实现一套系统中一个或几个功能,所有的服务组合在一起才能实现系统的完整功
- 1、概括在博客中,我们将讨论如何让Spring Security OAuth2实现使用JSON Web Tokens。2、Maven 配置首
- 持久化类Hibernate的整个概念是采取从Java类属性的值,并将持久到数据库表。一个映射文件Hibernate的帮助确定如何从拉动类的值
- 本文实例为大家分享了抢红包源码,供大家参考,具体内容如下1. 正确获取红包流程2. 软件介绍2.1 效果图:2.2 功能介绍2.2.1 账号
- 说明本案例使用Unity2019.3.8f1与AndropidStudio3.6.3源码git地址:https://github.com/g
- 在mybatis中sql是写在xml映射文件中的,如果sql中有一些特殊字符的话,在解析xml文件的时候就会被转义,如若不希望被转义,那该怎