2

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

这里有什么问题?

4

1 回答 1

4

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

因此,任何特定[ThreadStatic]await线程的内容,例如await正在运行的上下文,可靠地将工作推回同一线程)。

有一个AsyncLocal<T>可能更适合您的场景,并且可以在很大程度上交换ThreadLocal(有一些关于方向性的警告),但老实说,直接传递状态会更简单,而不是环境传递。

于 2020-10-05T08:53:23.597 回答