浅析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

标签:asnyclocal,threadlocal,c#
0
投稿

猜你喜欢

  • C# Random类的正确应用方法

    2021-06-25 14:56:17
  • Java数组与堆栈相关知识总结

    2023-11-12 06:12:18
  • java 创建线程的方法总结

    2023-02-25 20:20:30
  • springboot+rabbitmq实现智能家居实例详解

    2022-09-05 12:23:39
  • SpringAop @Aspect织入不生效,不执行前置增强织入@Before方式

    2021-09-18 04:00:58
  • Android 基于agora 开发视频会议的代码

    2021-11-30 02:53:04
  • C#单线程和多线程的端口扫描器应用比较详解

    2023-08-07 21:01:45
  • 快速了解hibernate配置文件与映射文件

    2023-11-04 23:02:26
  • Java中初始化List集合的八种方式汇总

    2021-09-20 22:31:54
  • Java编写日历表的3种方式

    2023-02-16 00:50:31
  • Java编程实现基于用户的协同过滤推荐算法代码示例

    2022-09-06 12:44:24
  • Android中的SpannableString与SpannableStringBuilder详解

    2022-03-02 22:04:55
  • Android隐藏顶部状态栏所遇到的问题

    2023-08-02 03:39:26
  • spring boot项目中MongoDB的使用方法

    2021-06-10 13:31:23
  • Android开发中Activity创建跳转及传值的方法

    2021-06-11 19:13:35
  • C语言实现两个矩阵相乘

    2023-07-22 12:41:20
  • Java 实战范例之员工管理系统的实现

    2023-03-31 08:09:33
  • Android Shape属性创建环形进度条

    2021-08-02 09:03:08
  • Android实现网易新闻客户端侧滑菜单(1)

    2023-09-12 00:54:05
  • Java自定义线程池的实现示例

    2022-01-23 01:28:04
  • asp之家 软件编程 m.aspxhome.com