Tagged: Delete
Timeout Dictionary
Warning: If you ever plan to open this kind of subject with your geek mates, be prepared for endless discussions regarding performance issues, “thread safe”-ing and other related subjects.
When dealing with large chunks of data, it might be a good idea to erase some of it once in a while, when is no longer needed. In my case I was continuously storing items in a dictionary and wanted to erase them after a timeout.
I created the following collection:
public class ExpireDictionary<T1, T2> : IDictionary<T1, T2> { // The collection that holds the dictionary paired with a DateTime value to track expiration private System.Collections.Concurrent.ConcurrentDictionary<DateTime, KeyValuePair<T1, T2>> collection = new System.Collections.Concurrent.ConcurrentDictionary<DateTime, KeyValuePair<T1, T2>>(); // The TimeSpan after which an item in the dictionary is expired and can be removed. private TimeSpan expiration; // The timer used for removing expired elements private Timer timer; // Initializes a new instance of the ExpireDictionary class. public ExpireDictionary(int intervalField, TimeSpan expirationField) { this.timer = new Timer(); this.timer.Interval = intervalField; this.timer.Elapsed += new ElapsedEventHandler(this.Tick); this.timer.Enabled = true; this.timer.Start(); this.expiration = expirationField; } // The TimeSpan after which an item in the dictionary is expired and can be removed. public TimeSpan Expiration { get { return this.expiration; } set { this.expiration = value; } } // The interval in milliseconds used for verifying the list and removing expired items. public int Interval { get { return (int)this.timer.Interval; } set { this.timer.Interval = value; } } // The handler for the event Elapsed of the timer private void Tick(object sender, EventArgs e) { foreach (var kp in this.collection.Keys.ToList()) { if (DateTime.Now - kp >= this.expiration) { KeyValuePair<T1, T2> removedKeyValuePair; this.collection.TryRemove(kp, out removedKeyValuePair); Console.WriteLine("removed element '{0}'", kp.ToString("yyyy.MM.dd HH:mm:ss:ffff")); } } } }
You can find the complete sources here.
There is plenty of room for improvement to the above solution, so please feel free to comment.
Later Edit: You might want to reconsider the key type of the private dictionary used here. I recently had a case where the precision of DateTime.Now wasn’t sufficient and it resulted in some ugly bugs where elements in the dictionary were overwritten.