.net 为什么AsyncLocal上的更改没有反映在Main方法上(C#)

13z8s7eq  于 2023-03-31  发布在  .NET
关注(0)|答案(1)|浏览(156)

为什么在调用Test()时,对data.Value的更改没有被反映到Main方法中?即使Test方法上没有await,这意味着它将被同步执行。

public class Data {
    public Data data;
    public int count;   
}

public class Program {
    public static AsyncLocal<Data> data = new();
    
    public static async Task Main(string[] args){
        data.Value = new Data{
            data = new Data{ count = 5 },
            count = 10
        };
        
        Console.WriteLine($"[Main] - Data = {data?.Value?.GetHashCode()}, Data Count = {data?.Value?.count}, " +
                          $"SubData Count = {data?.Value?.data?.count},\n ThreadId = {Thread.CurrentThread.ExecutionContext!.GetHashCode()}");           
        Console.WriteLine($"[Main] - AsyncLocal HashCode = {data.GetHashCode()}");
        
        var task = Test();
        
        Console.WriteLine($"[Main] - Data = {data?.Value?.GetHashCode()}, Data Count = {data?.Value?.count}, " +
                          $"SubData Count = {data?.Value?.data?.count},\n ThreadId = {Thread.CurrentThread.ExecutionContext.GetHashCode()}");                   
        Console.WriteLine($"[Main] - AsyncLocal HashCode = {data.GetHashCode()}");

        await task;
    }
    
    private static async Task Test()
    {
        data.Value = new Data{
            data = new Data{ count = 15 },
            count = 20
        };
        
        Console.WriteLine($"Data = {data.GetHashCode()}, Data Count = {data?.Value?.count}, SubData Count = {data?.Value?.data?.count}, " +
                          $"\n ThreadId = {Thread.CurrentThread.ExecutionContext.GetHashCode()}");  
        
        Console.WriteLine($"AsyncLocal HashCode = {data.GetHashCode()}");
    }
}

[Main] - Data = 58225482,Data Count = 10,SubData Count = 5,ThreadId = 54267293 [Main] - AsyncLocal HashCode = 18643596
Data = 18643596,Data Count = 20,SubData Count = 15,ThreadId = 33574638 AsyncLocal HashCode = 18643596
[Main] - Data = 58225482,Data Count = 10,SubData Count = 5,ThreadId = 54267293 [Main] - AsyncLocal HashCode = 18643596

68bkxrlz

68bkxrlz1#

为什么调用Test()时,data.Value的更改没有反映到Main方法中?
每个async方法获取执行上下文的 * 副本 *,其中包括AsyncLocal<T>值。换句话说,AsyncLocal<T>值不会“向上”流动。
从技术上讲,它们可以从非async方法“向上”流动,但我强烈建议不要依赖于这种行为;它很奇怪,如果任何中间方法从sync更改为async,它很容易被破坏。
即使Test方法上没有await,这意味着它将同步执行。
async关键字(或者从技术上讲,async关键字生成的状态机)捕获上下文。
Test同步执行,因为没有await;但是由于async关键字的原因,有一个副本。由于修改只发生在副本上,所以它无论如何都会丢失,即使Test同步执行。

相关问题