gpt4 book ai didi

c# - 从异步方法设置时,AsyncLocal 的值不正确

转载 作者:行者123 更新时间:2023-12-05 09:36:33 30 4
gpt4 key购买 nike

为什么从类的异步方法设置时不保留 AsyncLocal 字段的值。考虑这个例子:

var scope = new TestScope();

// The default value is 0
Console.WriteLine(scope.Counter.Value);

// Setting the vlaue to 2
await scope.SetValueAsync();

Console.WriteLine(scope.Counter.Value);

class TestScope
{
public readonly AsyncLocal<int> Counter = new AsyncLocal<int> { Value = 0 };

public async Task SetValueAsync()
{
this.Counter.Value = 2;

await Task.Yield();
}
}

预期的输出应该是:

0

2

但实际情况是:

0

0

为什么在退出 SetValueAsync 方法时异步上下文发生变化?

最佳答案

那是因为 AsyncLocal 具有写时复制语义。基本上,当从内部异步作用域更改时,会生成值的副本并且不会修改原始对象。

您可以通过将您的值包装在一个引用对象中来解决这个问题。那是因为即使你复制了一个引用,你最终还是在操作同一个对象:


class TestScope
{
public readonly AsyncLocal<StrongBox<int>> Counter = new AsyncLocal<StrongBox<int>> { Value = new StrongBox<int>(0) };

public int Value
{
get => Counter.Value.Value;
set => Counter.Value.Value = value;
}

public async Task SetValueAsync()
{
this.Value = 2;

await Task.Yield();
}
}

static async Task Test()
{
var scope = new TestScope();

// The default value is 0
Console.WriteLine(scope.Value);

// Setting the value to 2
await scope.SetValueAsync();

Console.WriteLine(scope.Value);
}

StrongBox<T> 只是将值类型包装在引用类型中的一种便捷方式。但任何其他引用类型都可以解决问题。

关于c# - 从异步方法设置时,AsyncLocal 的值不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65070450/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com