I got skooled today in .NET. I wrote a thread-local storage abstraction using named data slots some time ago. Avoid named data slots at all costs! Use the ThreadStaticAttribute instead. Not only is the ThreadStaticAttribute much easier to implement, but it performs better also. I had to wait till my code was in a near-prod environment before enough load could be generated to cause the race condition to occur. It took me about 2 days of debugging to find the issue. Most importantly, read the damn documentation before you attempt to write some threading code. There are some subtle issues in the .NET Base Class Library that I would have avoided if I had read the MSDN site. Very embarrassing.
From Microsoft:
The .NET Framework provides two mechanisms for using thread local storage (TLS): thread-relative static fields (that is, fields that are marked with the ThreadStaticAttribute attribute) and data slots. Thread-relative static fields provide much better performance than data slots, and enable compile-time type checking. For more information about using TLS, see Thread Local Storage: Thread-Relative Static Fields and Data Slots. (http://msdn.microsoft.com/en-us/library/system.threading.thread.allocatenameddataslot.aspx)
It's funny, I've gotten away with not using [ThreadStatic] or similar concepts all this time - not quite sure how though. I can see how it'd be useful, though it would seem to me that using Thread Local Storage would cause problems with testing in isolation.
ReplyDeleteAt work our system relies on TLS to store information about the request and retrieve it later for logging, but that approach always seemed a little bit too "magical" for my taste. I like to structure my code so in each method, it's obvious what you have access to (usually just the parameters). When TLS is used, the code may have to rely on the presence of a TLS value that was set by somewhere completely different in the code.
Unless TLS is used for caching of course, then it seems like a good use of it to me :)