When you are retrieving a property from the property bag you don’t want to block the all the property bags for all the webs, you just want to make sure the property you are looking for has not changed since you started the lock and that needs a dynamic way of creating locks.
I started this class with a dictionary but after using it for a while I realized that dictionaries are not thread safe for reading… so I changed it to a hash table.
public class Locks { /// <summary> /// This hashtable will provide a lock for every different key in the cache. Hashtables are threadsafe for one writer many readers scenario /// </summary> private static Hashtable LocksCollection = new Hashtable(); public static object GetLock(string Key, params object[] args) { if (args!=null) Key = string.Format(Key, args); if (!LocksCollection.ContainsKey(Key)) { lock (LocksCollection) if (!LocksCollection.ContainsKey(Key)) LocksCollection.Add(Key, new object()); } return LocksCollection[Key]; } }
With this new addition in the method for setting web properties we just lock that web property bag leaving the other webs in the server unloked. It looks like this:
/// <summary> /// Sets a web property to a given value. This method is thread safe. /// </summary> /// <param name="Key">The Key for the web property (case insensitive)</param> /// <param name="Value">Value to set the property to</param> public static void SetWebProperty(this SPWeb Web, string Key, string Value) { Key = Key.ToLower(); lock (Locks.GetLock("WebPropertyWriteLock - {0}", Web.ID)) { if (GetWebPropertyThreadSafe(Web, Key) != Value) { Web.Properties[Key] = Value; Web.Properties.Update(); } } }
No comments:
Post a Comment