Tagged: Dictionary
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.