千家信息网

如何理解C#中的AsnycLocal与ThreadLocal

发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,这篇文章主要讲解了"如何理解C#中的AsnycLocal与ThreadLocal",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解C#中的Asny
千家信息网最后更新 2025年01月20日如何理解C#中的AsnycLocal与ThreadLocal

这篇文章主要讲解了"如何理解C#中的AsnycLocal与ThreadLocal",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何理解C#中的AsnycLocal与ThreadLocal"吧!

AsnyncLocal与ThreadLocal都是存储线程上下文的变量,但是,在实际使用过程中两者又有区别主要的表现在:

  • AsyncLocal变量可以在父子线程中传递,创建子线程时父线程会将自己的AsyncLocal类型的上下文变量赋值到子线程中,但是,当子线程改变线程上下文中AsnycLocal变量值后,父线程不会同步改变。也就是说AsnycLocal变量只会影响他的子线程,不会影响他的父级线程。

  • TreadLocal只是当前线程的上下文变量,不能在父子线程间同步。

using System;using System.Threading;using System.Threading.Tasks;namespace await_aysnc{    class Program    {        static ThreadLocal ThreadObj = new ThreadLocal();        static AsyncLocal AsyncObj = new AsyncLocal();        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会获取到之前的上下文,此时会出现意料之外的问题,从现象上看报错可能会是一个概率性问题。

感谢各位的阅读,以上就是"如何理解C#中的AsnycLocal与ThreadLocal"的内容了,经过本文的学习后,相信大家对如何理解C#中的AsnycLocal与ThreadLocal这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0