private static readonly Hashtable sessionsTimeoutData = Hashtable.Synchronized(new Hashtable(5000));private static void ClearTimedoutSessions() { List keysToRemove = new List(); long now = DateTime.Now.Ticks; lock (sessionsTimeoutData) { TimeoutData timeoutData; foreach (DictionaryEntry entry in sessionsTimeoutData) { timeoutData = (TimeoutData)entry.Value; if (now - timeoutData.LastAccessTime > timeoutData.UserTimeoutTicks) keysToRemove.Add((ulong)entry.Key); } } foreach (ulong key in keysToRemove) sessionsTimeoutData.Remove(key); }
解决方法
lock (sessionsTimeoutData.SyncRoot) { // ... }
见http://msdn.microsoft.com/en-us/library/system.collections.hashtable.synchronized.aspx:
Enumerating through a collection is@H_502_2@ intrinsically not a thread-safe@H_502_2@ procedure. Even when a collection is@H_502_2@ synchronized,other threads can still@H_502_2@ modify the collection,which causes@H_502_2@ the enumerator to throw an exception.@H_502_2@ To guarantee thread safety during@H_502_2@ enumeration,you can either lock the@H_502_2@ collection during the entire@H_502_2@ enumeration or catch the exceptions@H_502_2@ resulting from changes made by other@H_502_2@ threads.
The following code example shows how@H_502_2@ to lock the collection using the@H_502_2@ SyncRoot during the entire@H_502_2@ enumeration:
06001