首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么当代码稍微重构时,AsyncLocal<T>会返回不同的结果?

为什么当代码稍微重构时,AsyncLocal<T>会返回不同的结果?
EN

Stack Overflow用户
提问于 2018-03-12 10:04:11
回答 3查看 13.1K关注 0票数 15

当我调用WrapperAsync时,AsyncLocalContext.Value返回null。当我在方法外部运行相同的代码块时,在Main方法中,AsyncLocalContext.Value不是空的(这正是我所期望的)。

功能是完全相同的,但结果是不同的。这是Asynclocal类的错误,还是有其他解释?

代码语言:javascript
运行
复制
internal class Program
{
    private static readonly AsyncLocal<string> AsyncLocalContext = new AsyncLocal<string>();

    private static void Main()
    {
        const string text = "surprise!";

        WrapperAsync(text).Wait();
        Console.WriteLine("Get is null: " + (AsyncLocalContext.Value == null));
        // AsyncLocalContext.Value is null

        var value = GetValueAsync(text).Result;
        AsyncLocalContext.Value = value;
        Console.WriteLine("Get is null: " + (AsyncLocalContext.Value == null));
        // AsyncLocalContext.Value is not null
        Console.Read();
    }

    private static async Task WrapperAsync(string text)
    {
        var value = await GetValueAsync(text);
        AsyncLocalContext.Value = value;
    }

    private static async Task<string> GetValueAsync(string text)
    {
        await Task.Delay(0);
        return text;
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-03-12 10:17:41

遵循这个链接MSDN上的AsyncLocal类

AsyncLocal<T>表示给定异步控制流(例如异步方法)的本地环境数据。

这意味着代码在从另一个async方法(如WrapperAsync )访问时使用不同的值,并且主线程包含另一个值

更新

不明显的事情,理解,但这是解释。异步程序中的控制流。当您不期望这样做时,您的线程就是这样改变的。

这就是控制流如何使用async的方式

代码语言:javascript
运行
复制
public class Program
{
    private static readonly AsyncLocal<string> AsyncLocalContext = new AsyncLocal<string>();

    public static void Main(string[] args)
    {
        AsyncLocalContext.Value = "No surprise";
        WrapperAsync("surprise!");
        Console.WriteLine("Main: " + AsyncLocalContext.Value);
    }

    private static async void WrapperAsync(string text)
    {
        Console.WriteLine("WrapperAsync before: " + AsyncLocalContext.Value);
        AsyncLocalContext.Value = text;
        Console.WriteLine("WrapperAsync after: " + AsyncLocalContext.Value);
    }
}

产出如下:

代码语言:javascript
运行
复制
WrapperAsync before: No surprise
WrapperAsync after: surprise!
Main: No surprise

/UPDATE

票数 16
EN

Stack Overflow用户

发布于 2019-05-24 21:54:10

AsyncLocal<T>是存储在当前线程的ExecutionContext上的环境数据。ExecutionContext在异步/等待调用链中自动地跨线程流动(详见Stephen的博客 )。当应用程序启动时,将使用默认的ExecutionContext,但是一旦通过AsyncLocal<T>.Value存储数据,就会为当前异步调用链(参见这里)创建一个新的ExecutionContext,并将环境数据添加到其中。这个新上下文被传播到下游调用。

Stephen讨论了这种行为这里 (向下滚动到AsyncLocal部分),并指出了以下要点:

AsyncLocal为上下文信息提供了一种“下行”异步调用的方式。请注意,该值没有“向上”流。

这就是为什么调用链上的AsyncLocal<T>更新没有反映在上游方法中的原因。

票数 31
EN

Stack Overflow用户

发布于 2022-03-17 18:08:27

我找到了一个解决办法,那就是使用Class而不是标量变量。这允许指针流到子节点,但不需要返回到父节点,就可以让父节点看到来自子节点的更改。

代码语言:javascript
运行
复制
internal class Program
{
    //class to store in AsyncLocal
    private class HoldData
    {
        public string Text { get; set; }
    }
    private static readonly AsyncLocal<HoldData> AsyncLocalContext = new AsyncLocal<HoldData>();

    private static void Main()
    {
        AsyncLocalContext.Value = new HoldData(); //this sets up the class to hold the data... then the child/parent use the same reference pointer
        const string text = "surprise!";

        WrapperAsync(text).Wait();
        Console.WriteLine("Get is null: " + (AsyncLocalContext.Value.Text == null));
        // AsyncLocalContext.Value.Text is not null

        var value = GetValueAsync(text).Result;
        AsyncLocalContext.Value.Text = value;
        Console.WriteLine("Get is null: " + (AsyncLocalContext.Value.Text == null));
        // AsyncLocalContext.Value.Text is not null
        Console.Read();
    }

    private static async Task WrapperAsync(string text)
    {
        var value = await GetValueAsync(text);
        AsyncLocalContext.Value.Text = value;
    }

    private static async Task<string> GetValueAsync(string text)
    {
        await Task.Delay(0);
        return text;
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49232514

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档