软件编程
位置:首页>> 软件编程>> C#编程>> 浅析C#中的AsnycLocal与ThreadLocal

浅析C#中的AsnycLocal与ThreadLocal

作者:沉默的雪糕  发布时间:2023-04-18 05:42:31 

标签:asnyclocal,threadlocal,c#

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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com