我使用一个具有[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
这里怎么了?
任务和线程在很大程度上是不相关的概念,而且重要的是:在最有趣的场景中,任何时候await
,您都有可能固有地更改线程。顺便说一句,这就是为什么不能有一个跨越await
的lock
,因为编译器知道lock
在两侧都需要相同的线程。
正因为如此,当您从await
返回时,任何特定于线程的东西,如[ThreadStatic]
,都可能是无效的(除非它恰好是同步或已完成操作上的无操作await
,或者如果正在播放的同步上下文可靠地将工作推回到同一线程(。
有一个AsyncLocal<T>
可能更适合您的场景,并且可以将很大程度上替换为ThreadLocal
(在方向性方面有一些注意事项(,但老实说,更简单的做法是显式地传递状态,而不是模糊地传递状态。