Reputation: 1214
I'm using a variable with [ThreadStatic]
attribute to store the current active Session
for each socket (I'm using WebSocket as the connection type). In the beginning of socket connect
, I assign its value with a new Session
object, and then executing a Task
method to get an output. After the Task
is completed, the Session
value become null
.
ThreadStatic
declaration:
public class Session
{
...
[ThreadStatic] public static Session _session;
}
Task method to call:
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}";
}
The task execution part:
// 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
What's wrong here?
Upvotes: 2
Views: 852
Reputation: 1064114
Tasks and threads are largely unrelated concepts, and importantly: in most interesting scenarios, any time you await
, you are inherently potentially changing thread. Incidentally, that is why you can't have a lock
that spans an await
, because the compiler knows that lock
requires the same thread at both sides.
Because of this, anything that is thread-specific, such as [ThreadStatic]
, is probably going to be invalid when you get back from the await
(unless it happens to be a no-op await
on a synchronous or completed operation, or if there is a sync-context in play that is reliably pushing work back to the same thread).
There is an AsyncLocal<T>
that is probably more suitable for your scenario, and can largely be swapped for ThreadLocal
(with some caveats around directionality), but to be honest it would be simpler to just pass the state along explicitly, rather than ambiently.
Upvotes: 4