Caching in WinForms
Just out of curiosity I decided to try out some caching experiments in winforms. I wasn’t out to do any performance counting or anything, but I was playing around with the caching application block. After messing with it for a while, I remembered that I had already seen a very easy implementation for caching even before the caching application block was released. This caching implementation actually used the System.Web.Caching.Cache class (usually used in ASP.NET applications) for the caching.
So, I decided to try it out. It turned out to be one of the simplest things ever.
Simple steps to using the ASP.NET cache in a non-web application:
- Add System.Web to your references
- Get the actual cache object using
private Cache m_Cache;
m_Cache = HttpRuntime.Cache;
- Now you can use all those wonderful cache features such as expirations and file dependencies in your application.
One more thing:
- You do not need IIS installed on the machine in order to work with the Cache object
Now, here’s something funny I discovered when using the Cache object; one of the coolest features that it exposes it “sliding expiration time” and “absolute expiration time” for stuff you put in there. Basically this means that I can put my stuff in the cache, and make that stuff “expire” say, 20 minutes from now(sliding expiration). Not only that. I provide a callback function that will be called when that item actually expires so I can re-fill the cached item and thus “refresh” it. If we’re dealing with absolute expiration time, it will only be called on a specific date and time provided by me. For example “expire this item on 12/12/03 00:00”.
Very cool. BUT – here’s a little snag I fell into:
I added an item to the cache like so:
m_Cache.Add("ds",ds, null,DateTime.MaxValue,TimeSpan.FromSeconds(3),CacheItemPriority.High,new CacheItemRemovedCallback(OnItemRemove));
without getting into too much detail – I’m adding an item that will expire 3 seconds from now (sliding expiration) and want my callback function to be call when it expires.
On my callback function I re-add the expired item in the same way – to expire in 3 seconds. And so on. I have a form and a button that when clicked tries to get the value of the cached item.
I put a Debug message in my callback function to know when I have an expired item.
Now I run the application. I don’t click anything for 10 seconds. Then I click the button. What do you think happened?
The callback was not called until I clicked the button
Yep – that’s right. I get the callback only the first time my code tries to access the item after it has already expired. Can you see why this might be a bad thing?
Suppose I have some very complicated data cached in there. And suppose it takes me 30 seconds to refresh that data. Instead of this data being refreshed an given intervals, I am faced with the fact that the next used that tries to access this data will have to wait 30 seconds for it. This fact is also stated in this MSDN article.
I wish I had a more deterministic way of using this event.
Anyway – some pointers about using this Web.Caching.Cache (some may not agree, but there are my views):
- If you need caching within your appdomain, and not shared in other places – this is the fastest and easiest way to go.
- For more complicated stuff (like sharing on a larger scope, deterministic expiry times and the ability to provide your own dependency resources) look to the Caching application block