Subscribe

RSS Feed (xml)

Create a Thread-Safe Collection Instance

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.

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.

No comments:

Post a Comment

Archives

LocalsAdda.com-Variety In Web World

Fun Mail - Fun in the Mail