views:

33

answers:

1

I'm trying to build a process that will repopulate an item that was inserted into cache every 30 minutes. I inserted the item into Cached to expire after 30 minutes. I setup a delegate (http://msdn.microsoft.com/en-us/library/system.web.caching.cacheitemremovedcallback(v=VS.90).aspx) to be called when the cached item expired. My goal was when the delegate was called was to rebuild the item and insert it back into cached.

The issue I found with the MSDN article above was that it was using a holding the page instance open until the delegate was called. Instead of had it call another class that was static (vb shared). This caused a different problem -- the delegate lost context. When I tried to add back into the cache the HttpContext.Current was null.

Is there a way I can repopulate an item in cache every 30 minutes in ASP.NET without keeping page instances around? Note, I cannot use a sliding expiration date because the content will change.

+1  A: 

Firstly, you know you could just repopulate the cache whenever you have a new request after the 30 minutes have expired. I mean why bother putting in the cache if you have no requests that need that data.

Secondly, we've had a similar need a while ago and anyway ... the basic ideea was:

1.Keep a reference to the App's cache so we can acces it from an async thread

    public static System.Web.Caching.Cache BackgroundCache;    
    public static System.Web.HttpServerUtility BackgroundServer;

then assign them in Global.asax's Application_Start

 BackgroundCache = System.Web.HttpContext.Current.Cache;
 BackgroundServer = System.Web.HttpContext.Current.Server;

2.Start a Timer also on Application_Start, that will run on an async thread every 30 mins.

3.Populate the cache from there using BackgroundCache and BackgroundServer

Radu094
What I'm trying to avoid is the delay when it rebuilt after 30 minutes. It takes 2 to 3 seconds to build vs. milliseconds to pull from Cache. It does sounds like a better idea to start the process from Global.asax's Application_Start and have it sleep. Currently the it is put into Cache based on a user event.
Josh
I'm going to go with a hybrid approach, I'll keep using the delegate model but call the static references in Global.asax instead of HttpContext. Any guesses on overhead for this approach? I'm assuming it is small because we are just declaring a reference and not keeping a copy because we are not declaring instances.
Josh
Basically there shoudln't be any overhead. It's just a dereference just like using the normal HttpContext. The only problems will appear if you start using server farms or gardens, but that's another story.
Radu094
We have two web servers that are load balanced. Besides each having a different copies of cache, which works for us, is there another issue?
Josh
Well, it's not just the cache that will be duplicated: The expiration delegate will only fire on the server actually hosting the cached element that expired. Granted it will fire eventually on both servers, just at different times. This means the servers will have different versions of the cached item at the same moment.
Radu094