保留异步上下文中的本地变量值

posted at 2020.12.7 16:23 by 风信子

在基于Task的异步等待上下文中,ThreadLocal<T>类型的本地变量无法发挥作用。

请思考以下例子。

        ThreadLocal<string> local = new ThreadLocal<string>();   

        async Task WorkAsync()

        {

            local.Value = "Hello cx";

            Console.WriteLine("异步等待前:{0}", local.Value);

            await Task.Delay(150);

            Console.WriteLine("异步等待后:{0}", local.Value);

        }

在进入异步等待前,本地变量将字符串常量赋值为“Hello cx”,随后调用Delay方法,并异步等待方法返回。回到当前上下文后,本地变量的值变为默认值(字符串的默认值为null),也就是说,之前赋值的字符串“Hello cx”已经读不到了。

这是因为基于并行任务的异步上下文是由内部框架自动调度的,异步等待前后,本地变量可能处于不同的线程上,即await语句使用前后的代码并不是在同一个线程上,所以在等待方法返回后就取不到本地变量的值了。要解决这个问题,可以用AsyncLocal<T>类替换ThreadLocal<T>类。AsyncLocal<T>类能够在异步上下文之间保留原有的数据,即使异步等待的前后的代码不在同一个线程上,也能够访问之前设置的值。

以下实例将演示AsyncLocal<T>类的用法。

【操作流程】

步骤1:新建一个控制台应用程序项目。

步骤2:Program类中声明一个静态字段。

static AsyncLocal<string> local = new AsyncLocal<string>();

步骤3:定义一个异步方法。

        static async Task RunThisCodeAsync()

        {

            local.Value = "Follow me";

            Console.WriteLine("异步等待前:{0}", local.Value);

            await Task.Delay(150);

            Console.WriteLine("异步等待后:{0}", local.Value);

        }

步骤4:main方法中调用RunThisCodeAsync方法。

 RunThisCodeAsync().Wait();

步骤5:运行应用程序,控制台输出如下:

  可以看到,等待之前所赋的值,在异步上下文返回后仍然能顺利地读取。

Tags: , , , ,

IT技术

Add comment

  Country flag

biuquote
微笑得意调皮害羞酷大笑惊讶发呆喜欢可怜尴尬闭嘴噘嘴皱眉伤心抓狂呕吐坏笑漫骂发怒
Loading