Possibly one of the coolest tricks I've learned in awhile, adding the ThreadStaticAttribute to your .NET static field makes it static but only visible or accessible within the context of the current executing thread. So there can be multiple threads executing at the same time, referencing the same thread-static field, but the value returned is potentially different for each individual thread. This allows you to easily share a static value between different classes / methods of a thread while still encapsulating it from other threads. Because of this it is slightly more insulated than a normal static field, and can be useful in some cases where you don't necessarily want to chain-pass an object as a parameter from method to method, especially if the parameter is passed across many different classes with method calls many layers deep.
Perhaps a good use case for the ThreadStaticAttribute is managing database transactions. Often you need to pass the Transaction object between different method calls, and frequently these method calls are divided into different classes. You can declare a separate class that holds a thread-static reference to the current Transaction which eliminates the need to chain pass it as a parameter between the different methods. Of course this is not strictly necessary anymore since the introduction of the TransactionScope class, but guess what, this is basically exactly how the TransactionScope class is implemented - the associated Transaction class maintains a thread-static reference to the current Transaction.
A word of warning though, be careful when using the ThreadStaticAttribute if you are not in complete control of the thread. Examples of potentially dangerous situations are Thread Pools, ASP .NET, and WCF. I'm not saying that you absolutely shouldn't use the ThreadStaticAttribute in these situations, but you need to be knowledgeable about the thread's lifecycle so as to avoid unexpected errors. In cases like these you need to handle when and if the thread is re-used, terminated, or if your code runs on different threads during different phases of its lifecycle. So, if you use the thread-static feature then do so wisely, cautiously, and test thoroughly. It's not a feature you should overuse or abuse, but occasionally it may be a good solution for some niche problem.
Below is an example of actually using the ThreadStaticAttribute:
[ThreadStatic] private static string foo;
Warning: ThreadStaticAttribute fields are initialized in the static constructor which only executes once. In the example below the variable foo will only be initialized to "TEST" for the first thread, but the value will be null for subsequent threads.
[ThreadStatic] private static string foo = "TEST";
To work around this problem trying using a property to access and initialize the ThreadStaticAttribute field:
[ThreadStatic] private static string _foo; public static string Foo { get { return _foo ?? "TEST"; } }
Note: There's also something new in .NET 4.0 called ThreadLocal, which is similar to ThreadStatic but doesn't require the variable to be static. I may write a separate blog about it sometime in the future.
Links:
No comments:
Post a Comment