In a normal/synchronous/single-threaded console app, NDC.Push works fine for managing the \'current item\' (potentially at multiple levels of nesting, but just 1 level for t
There isn't a good story for async
logical call contexts right now.
CallContext
can't be used for this. The logical CallContext
doesn't understand how async
methods return early and resume later, so it will not always work correctly for code that uses simple parallelism such as Task.WhenAll
.
Update: CallContext
was updated in .NET 4.5 RTW to correctly work with async
methods.
I looked into log4net; LogicalThreadContext
is documented as using CallContext
, but there was a bug that made it use the non-logical contexts (fixed in their SVN on Feb 2, 2012; the current 1.2.11 release does not include that fix). Even when it's fixed, though, it'll still not work with async
(because the logical CallContext
doesn't work with async
).
When I need an async
logical call context, I make a class that contains the context data and keep all of my async
methods in a functional style as instance members of that class. This is certainly not an ideal solution, but it's a dirty hack that works.
In the meantime, please upvote the suggestion that Microsoft provide some mechanism for this.
P.S. A concurrent dictionary keyed by Task
won't work, because async
methods are not necessarily running tasks (i.e., in your example code, at the using
statement, Task.CurrentId
would be null
because there is no task actually executing at that point).
And thread affinity has its own problems, too. You actually end up needing a separate thread for each independent asynchronous operation. Bye-bye, scalability...