【问题标题】:Losing [ThreadStatic] value after calling a Task调用任务后丢失 [ThreadStatic] 值
【发布时间】:2021-01-20 02:43:11
【问题描述】:

我正在使用具有[ThreadStatic] 属性的变量来存储每个套接字的当前活动Session(我使用WebSocket 作为连接类型)。在套接字connect 的开头,我将其值分配给一个新的Session 对象,然后执行Task 方法以获取输出。 Task完成后,Session的值变成null

ThreadStatic 声明:

public class Session
{
    ...
    [ThreadStatic] public static Session _session;
}

要调用的任务方法:

public async Task<string> Connect()
{
    var path = Path.Combine(Directory.GetCurrentDirectory(), "storyboard", "1.json");
    var json = await File.ReadAllTextAsync(path, Encoding.UTF8);

    return $"\"i\":{this.id},\"m\":\"build\",\"a\":{json}";
}

任务执行部分:

// Session._session == null ? --> false (here, the value still exists)
var res = await obj.Item1.Execute(met, args); // execute a method with async call
await Session._session.Send(res); // Session._session == null ? --> true

这里有什么问题?

【问题讨论】:

  • 为什么不在最终代码示例中将其保存在局部变量中? var session = new Session(); 仍应在最后一行正确设置 session
  • 这只是一个例子,我在另一个地方(不是本地)初始化了Session._session值,我需要在很多地方使用它。
  • 那是因为在 ASP.NET Core 中有no synchronization context。继续在随机线程上恢复。即使在 ASP.NET 非 Core 中,方法也是 flawed
  • 还有其他方法可以解决这个限制吗?

标签: c# asp.net-core threadstatic


【解决方案1】:

任务和线程在很大程度上是不相关的概念,重要的是:在大多数有趣的场景中,任何时候您await,您都可能更改线程。顺便说一句,这就是为什么你不能有一个跨越awaitlock,因为编译器知道lock 需要在两端使用相同的线程。

因此,当您从await 返回时,任何特定于线程的东西,例如[ThreadStatic],都可能是无效的(除非它恰好是一个无操作await 在同步或完成的操作,或者如果有一个同步上下文正在运行,它可靠地将工作推回同一线程)。

有一个AsyncLocal&lt;T&gt; 可能更适合您的场景,并且可以在很大程度上替换为ThreadLocal(有一些关于方向性的警告),但老实说它会是更简单 只是显式地传递状态,而不是环境。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-31
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
  • 2013-05-20
相关资源
最近更新 更多