【问题标题】:Why does AsyncLocal<T> propagate to child threads whereas ThreadLocal<T> does not?为什么 AsyncLocal<T> 会传播到子线程,而 ThreadLocal<T> 不会?
【发布时间】:2017-05-05 22:01:59
【问题描述】:

我不得不用 AsyncLocal 替换代码中 ThreadLocal 的使用,以便在等待异步操作时保持“环境状态”。

但是,AsyncLocal 的一个令人讨厌的行为是它“流向”子线程。这与 ThreadLocal 不同。有什么办法可以预防吗?

class Program
{
    private static readonly ThreadLocal<string> ThreadState = new ThreadLocal<string>();
    private static readonly AsyncLocal<string> AsyncState = new AsyncLocal<string>();

    static async Task MainAsync()
    {
        ThreadState.Value = "thread";
        AsyncState.Value = "async";

        await Task.Yield();

        WriteLine("After await: " + ThreadState.Value); 
        WriteLine("After await: " + AsyncState.Value); // <- I want this behaviour

        Task.Run(() => WriteLine("Inside child task: " + ThreadState.Value)).Wait(); // <- I want this behaviour
        Task.Run(() => WriteLine("Inside child task: " + AsyncState.Value)).Wait();

【问题讨论】:

    标签: c# .net multithreading asynchronous


    【解决方案1】:

    AsyncLocal 将数据存储在执行上下文中,大多数 API(包括Task.Run)会自动执行该上下文。

    防止这种情况的一种方法是在需要时显式抑制流量:

    using (ExecutionContext.SuppressFlow())
    {
        Task.Run(...);
    }
    

    【讨论】:

    • Task.Run 传输 AsyncLocal 数据这一事实是否意味着它应该是“线程安全的”?而这不是必需的,因为 TaskLocal 将(并且可以)只能由单个线程访问?
    • 这样做还有什么损失?
    猜你喜欢
    • 1970-01-01
    • 2022-06-10
    • 2017-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    相关资源
    最近更新 更多