I've a C# web page in which I'm storing a List<> object in the server cache, using HttpContext.Current.Cache. The object is saved in the cache after the first page load. When I refresh the page though, the cache object is null. Any thoughts?
Also, I'd like to set up a "job" to recreate the object every 30 minutes. I'd like to serve up the cached version until the new one is created, and then replace the old with the new. How do I do that?
In my Global.asax, in Application_Start, I've got the following:
HttpRuntime.Cache.Insert("MainADList", Uf.GetUsers(), null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(30));
When I need it, I do the following:
MainADList = (Users)HttpRuntime.Cache["MainADList"];
Which is for the most part null. Not always, but almost always.
Even if you populate your cache using Cache.NoAbsoluteExpiration
+ Cache.NoSlidingExpiration
, ASP.NET can remove items from the cache (i.e.: when the free system memory is low).
Pass CacheItemPriority.NotRemovable
to Cache.Insert() to prevent that from happening. Lookup CachéItemPriority on MSDN.
An IIS application pool restart by long idle time, web.config/binary change, etc. will also wipe your cache. Check this other SO post, HttpRuntime.Cache.Insert() Not holding cached value
About creating a job to refresh the cache; I don't think there is a rule of thumb for the best Cache strategy. It will heavily depend on how your users interact with your web page, how often, how concurrent, and specially, how much time does it take to generate that data when the cache is not hit.
If the time it takes to generate the data is unacceptable for any user, you can set up a job that refreshes the cache, but it's interval should be less than the sum of the cache TTL + time that the generation/retrieval takes. For example, if your cache is 30m and it takes 2m to generate the data, your refresh interval must be 28m or less, to avoid any user to hit an empty cache.
Can you use the System.Runtime.Caching
instead. That way you're not dependent on the HttpRuntime namespace.
I suspect you're getting null because .Net is clearing it due to web-server restarts. Would it be better to do something along the lines of
public List<User> GetUsers()
{
var cache = System.Runtime.Caching.MemoryCache.Default;
if (cache["MainADList"] == null)
{
// Rebuild cache. Perhaps for Multithreading, you can do object locking
var cachePolicy = new System.Runtime.Caching.CacheItemPolicy() { AbsoluteExpiration = DateTime.Now + TimeSpan.FromMinutes(30) };
var users = Uf.GetUsers();
cache.Add(new System.Runtime.Caching.CacheItem("MainADList", users), cachePolicy);
return users;
}
return cache["MainADList"] as List<User>;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With