4.9 Create a Thread-Safe Collection Instance


Problem

You need multiple threads to be able to safely access the contents of a collection concurrently.

Solution

Use lock statements in your code to synchronize thread access to the collection, or access the collection through a thread-safe wrapper.

Discussion

By default, the standard collection classes from the System.Collections and System.Collections.Specialized namespaces will support multiple threads reading the collection's content concurrently. However, if one or more of these threads tries to modify the collection, you will almost certainly encounter problems. This is because the operating system can interrupt the actions of the thread while modifications to the collection have been only partially applied. This leaves the collection in an indeterminate state, which will almost certainly cause another thread accessing the collection to fail, return incorrect data, or corrupt the collection.

Note  

The use of thread synchronization introduces a performance overhead. The decision to make collections non-thread-safe by default provides better performance for the vast majority of situations where multiple threads are not used.

The most commonly used collections all implement a static method named Synchronized; this includes the ArrayList , Hashtable , Queue , SortedList , and Stack classes from the System.Collections namespace. The Synchronized method takes a collection object of the appropriate type as an argument and returns an object that provides a synchronized wrapper around the specified collection object. The wrapper object is returned as the same type as the original collection, but all of the methods and properties that read and write the collection ensure that only a single thread has access to the collection content concurrently. The following code shows how to create a thread-safe Hashtable . (You can test if a collection is thread-safe using the IsSynchronized property.)

 // Create a standard Hashtable Hashtable hUnsync = new Hashtable(); // Create a synchronized wrapper Hashtable hSync = Hashtable.Synchronized(hUnsync); 

The collection classes such as HybridDictionary , ListDictionary , and StringCollection from the System.Collections.Specialized namespace don't implement a Synchronized method. To provide thread-safe access to instances of these classes, you must implement manual synchronization using the object returned by their SyncRoot property, as shown in the following code:

 // Create a NameValueCollection. NameValueCollection nvCollection = new NameValueCollection(); // Obtain a lock on the NameValueCollection before modification. lock (((ICollection)nvCollection).SyncRoot) {     // Modify the NameValueCollection... } 

Notice that the NameValueCollection class derives from the NameObjectCollectionBase class, which uses explicit interface implementation to implement the ICollection.SyncRoot property. As shown, you must cast the NameValueCollection to an ICollection instance before you can access the SyncRoot property. Casting is not necessary with other specialized collection classes such as HybridDictionary , ListDictionary , and StringCollection , which do not use explicit interface implementation to implement SyncRoot .

If you need to use the synchronized collection class extensively, you can simplify your code by creating a new class that derives from the collection class you need to use. Override the members of the base class that provide access to the collection's content and perform synchronization before calling the equivalent base class member. You would normally use the lock statement to synchronize on the object returned by the SyncRoot property of the base class as discussed previously. However, by creating a derived class it's also possible to implement more advanced synchronization techniques, such as using the System.Threading.ReaderWriterLock to allow multiple reader threads but only a single writer thread.




C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

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