Recipe18.1.Creating Per-Thread Static Fields


Recipe 18.1. Creating Per-Thread Static Fields

Problem

Static fields, by default, are shared between threads within an application domain. You need to allow each thread to have its own nonshared copy of a static field, so that this static field can be updated on a per-thread basis.

Solution

Use ThreadStaticAttribute to mark any static fields as not shareable between threads:

 using System; using System.Threading; public class Foo {     [ThreadStaticAttribute( )]     public static string bar = "Initialized string"; } 

Discussion

By default, static fields are shared between all threads that access these fields in the same application domain. To see this, you'll create a class with a static field called bar and a static method to access and display the value contained in this field:

 using System; using System.Threading; public class ThreadStaticField {     public static string bar = "Initialized string";     public static void DisplayStaticFieldValue()     {         string msg =             string.Format("{0} contains static field value of: {1}",                 Thread.CurrentThread.GetHashCode(),                 ThreadStaticField.bar);         Console.WriteLine(msg);     } } 

Next, create a test method that accesses this static field both on the current thread and on a newly spawned thread:

 public static void TestStaticField( ) {     ThreadStaticField.DisplayStaticFieldValue( );     Thread newStaticFieldThread =         new Thread(ThreadStaticField.DisplayStaticFieldValue);     newStaticFieldThread.Start( );     ThreadStaticField.DisplayStaticFieldValue( ); } 

This code displays output that resembles the following:

 9 contains static field value of: Initialized string 10 contains static field value of: Initialized string 9 contains static field value of: Initialized string 

In the preceding example, the current thread's hash value is 9 and the new thread's hash value is 10. These values will vary from system to system. Notice that both threads are accessing the same static bar field. Next, add the ThreadStaticAttribute to the static field:

 public class ThreadStaticField {          [ThreadStaticAttribute( )]     public static string bar = "Initialized string";     public static void DisplayStaticFieldValue()     {         string msg =             string.Format("{0} contains static field value of: {1}",                 Thread.CurrentThread.GetHashCode(),                 ThreadStaticField.bar);         Console.WriteLine(msg);     } } 

Now, output resembling the following is displayed:

 9 contains static field value of: Initialized string 10 contains static field value of: 9 contains static field value of: Initialized string 

Notice that the new thread returns a null for the value of the static bar field. This is the expected behavior. The bar field is initialized only in the first thread that accesses it. In all other threads, this field is initialized to null. Therefore, it is imperative that you initialize the bar field in all threads before it is used.

Remember to initialize any static field that is marked with ThreadStaticAttribute before it is used in any thread. That is, this field should be initialized in the method passed in to the ThreadStart delegate. You should make sure to not initialize the static field using a field initializer as shown in the prior code, since only one thread gets to see that initial value.


The bar field is initialized to the "Initialized string" string literal before it is used in the first thread that accesses this field. In the previous test code, the bar field was accessed first, and, therefore, it was initialized, in the current thread. Suppose you were to remove the first line of the TestStaticField method, as shown here:

 public static void TestStaticField( ) {  // ThreadStaticField.DisplayStaticFieldValue( );     Thread newStaticFieldThread =         new Thread(ThreadStaticField.DisplayStaticFieldValue);     newStaticFieldThread.Start( );     ThreadStaticField.DisplayStaticFieldValue( ); } 

This code now displays similar output to the following:

 10 contains static field value of: Initialized string 9 contains static field value of: 

The current thread does not access the bar field first and therefore does not initialize it. However, when the new thread accesses it first, it does initialize it.

Note that adding a static constructor to initialize the static field marked with this attribute will still follow the same behavior. Static constructors are executed only one time per application domain.

See Also

See the "ThreadStaticAttribute Attribute" and "Static Modifier (C#)" topics in the MSDN documentation.



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net