ASP.NET caching asynchronously

Firstly, I think I should refer to this article , which pretty much does what I do.

Here is my problem: I had a user control on my site that would have to cache some data for at least 15 minutes, and then pull the data from the database. The problem is that pulling takes about 7-10 seconds to get the result out of the database.

My thought is that I can configure the cache as two hours and then have the property in the cached object to tell when the object was loaded (let me call this property LoadDate). Then I would get code to cache the object.

  • If it is null, I have no choice but to pull the data out synchronously and then load the user control
  • If it is not null, I want to continue and load the data into my user control from the cached object. Then I have to check the LoadDate property. If it has been 15 minutes or more, configure the asynchronous process to reload the cache.
    • There must be a process to lock the cache object for this when updating it
    • I need an if statement, which says that if an object is locked, then just forget about updating it. This will be for subsequent page loads by other users - since the first user will already update the cache, and I do not want the cache update to be repeated again and again; It should be updated only by the first call. Remember that I am already loading my user control before I even do a cache check.

In the article I linked to earlier, the answer configures the cache update fine, but I don't think it is asynchronous. The question began with asynchronous use with Page.RegisterAsyncTask. [Question 1] I can’t find any information on whether the asynchronous process will continue to work even if the user leaves the page?

[Question 2] Does anyone have a good idea on how to do this? I have code, but it has grown for a very long time and seems to be working incorrectly.

+4
source share
1 answer

Question 1 (RegisterAsyncTask)

It is very important to remember: from the point of view of the client / user / browser, this does NOT make the request asynchronous. If the Task you are registering takes 30 seconds, the browser will still wait another 30 seconds. The only thing RegisterAsyncTask does is to free your workflow back to IIS for the duration of the asynchronous call. Do not get me wrong - this is still a valuable and important technique. However, for the user / browser that makes this particular request, it does not have a noticeable effect on response time.

Question 2

This may not be the best solution to your problem, but this is what I used in the past that could help: when you add your item to the cache , specify absoluteExpiration and onRemoveCallback. Create a function that receives the latest data and puts it in the cache: this is a function that you must pass as onRemoveCallback. Thus, each time your cached data expires, a callback occurs to return the new data to the cache; because the callback results from a cache expiration event, there is no user request waiting 7-10 seconds needed to cache fresh data.

This is not a perfect design. Some reservations:

  • How to load cache initially? The easiest way is to call the cache loader function from the Application_Start function.
  • Every 15 minutes, a window with 7-10 seconds will appear in which the cache is empty. Any requests during this time will have to receive the data themselves. Depending on your patterns of using the system, this may be an acceptable small window, and during it there will only be very few requests.
  • Cache fault tolerance is not guaranteed when your cache code expires. If the system is under extremely heavy load, there may be a delay before the callback is called and the cache is reloaded. Again, depending on the use of your system, this may be a problem or a problem.

Sorry, I don’t have a bulletproof answer for you (I will follow this thread - maybe another SO'er does!). But, as I said, I used this approach with some success, and if your system does not have an extremely high load, it should help resolve the issue.

Edit: slight deviation from the above approach based on OP comment

You can cache a dummy value and use it exclusively to run the refreshCachedData function. It is not particularly elegant, but I have done it before. :)

To develop: save your actual data in a cache with the "MyData" key, without expiration and without onRemoveCallback. Each time you cache fresh data in "MyData", you also add a dummy value to your cache: "MyDataRebuildTrigger", after 15 minutes and with onRemoveCallback, which restores your actual cached data. Thus, there is no 7-10 second space when "MyData" is empty.

+3
source

All Articles