using ThreadStatic variables with async/await

async-await, c#, multithreading, synchronization

Solution

You could use `CallContext.LogicalSetData` and `CallContext.LogicalGetData`, but I recommend you don't because they don't support any kind of "cloning" when you use simple parallelism (`Task.WhenAny` / `Task.WhenAll`).

I opened a UserVoice request for a more complete `async`-compatible "context", explained in more detail in an MSDN forum post. It does not seem possible to build one ourselves. Jon Skeet has a good blog entry on the subject.

So, I recommend you use argument, lambda closures, or the members of the local instance (`this`), as Marc described.

And yes, `OperationContext.Current` is not preserved across `await`s.

Update: .NET 4.5 does support `Logical[Get|Set]Data` in `async` code. Details on my blog.

Problem

With the new async/await keywords in C#, there are now impacts to the way (and when) you use ThreadStatic data, because the callback delegate is executed on a different thread to one the `async` operation started on. For instance, the following simple Console app: ``` [ThreadStatic] private static string Secret; static void Main(string[] args) { Start().Wait(); Console.ReadKey(); } private static async Task Start() { Secret = "moo moo"; Console.WriteLine("Started on thread [{0}]", Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Secret is [{0}]", Secret); await Sleepy(); Console.WriteLine("Finished on thread [{0}]", Thread.CurrentThread.ManagedThreadId); Console.WriteLine("Secret is [{0}]", Secret); } private static async Task Sleepy() { Console.WriteLine("Was on thread [{0}]", Thread.CurrentThread.ManagedThreadId); await Task.Delay(1000); Console.WriteLine("Now on thread [{0}]", Thread.CurrentThread.ManagedThreadId); } ``` will output something along the line of: ``` Started on thread [9] Secret is [moo moo] Was on thread [9] Now on thread [11] Finished on thread [11] Secret is [] ``` I've also experimented with using `CallContext.SetData` and `CallContext.GetData` and got the same behaviour. After reading some related questions and threads: - CallContext vs ThreadStatic - http://forum.springframework.net/showthread.php?572-CallContext-vs-ThreadStatic-vs-HttpContext&highlight=LogicalThreadContext - http://piers7.blogspot.co.uk/2005/11/threadstatic-callcontext-and_02.html it seems that frameworks like ASP.Net explicitly migrates the HttpContext across threads, but not the `CallContext`, so perhaps the same thing is happening here with the use of `async` and `await` keywords? With the use of the async/await keywords in mind, what's the best way to store data associated with a particular thread of execution that can be (automatically!) restored on the callback thread? Thanks,

Original source

Related problems