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.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s