0

I have implemented asp.net caching. But I am getting weird results

Unlike most caching where you are trying to avoid the amount of hits to the DB. I am trying to avoid any hits to the DB by the user. This is b/c the amount of time the fist page takes to load. It is basically a dashboard with a lot of charts and long running queries

I tried several techniques 1) Have the cache time very long and have a schedule process expire and get new cache. 2) and on RemoveCallback

In the second option I have all the cache go through a static class I created. The purpose is as it expires to refresh the data. Here is what I am calling.

Cache.Insert(dbCacheString, dtNetwork, null, DateTime.Now.AddHours(2),
    System.Web.Caching.Cache.NoSlidingExpiration, CacheItemPriority.High, 
    new CacheItemRemovedCallback(CacheManager.CacheRemovedCallback));

    public static class CacheManager
    {
        private static Hashtable times = new Hashtable();
        private static bool isRefreshingCache = false;

        public static void CacheRemovedCallback(String key, object value,
            CacheItemRemovedReason removedReason)
        {
            RefreshCache(key);
        }

        public static void StartCache()
        {
            string lcUrl = "http://localhost/ratingspage/";
            // *** Establish the request 

            try
            {

                WebClient client = new WebClient();
                client.Credentials = new NetworkCredential("xxx", "xxx", 
                    "xxx");
                byte[] myDataBuffer = client.DownloadData(lcUrl);


            }
            catch (Exception ex)
            {
                ErrHandler.WriteError(ex.Message + "\n" + 
                    ex.StackTrace.ToString());
                LogUtil.LogDebugMessages(ex.Message + ":" + 
                    ex.StackTrace.ToString());
            }

        }

        public static void RefreshCache(string key)
        {
            string controlname = "";
            if ( key.ToLower().StartsWith("control:") )
            {
                string[] tmp = key.Split(':');
                if (tmp.Length > 1)
                    controlname = tmp[1];
                else
                    return;
            }
            else
                return;

            string lcUrl = "http://localhost/ratingspage/Admin/" + "
                "LoadControl.aspx?CachingSpider=true&Control=" + controlname;
            string lcHtml = isRefreshingCache.ToString();
            // *** Establish the request 

            if (!isRefreshingCache)
            {

                isRefreshingCache = true;
                lcHtml = isRefreshingCache.ToString();
                try
                {

                    WebClient client = new WebClient();
                    client.Credentials = new NetworkCredential("xxx", 
                        "xxx", "xxx");
                    byte[] myDataBuffer = client.DownloadData(lcUrl);
                    lcHtml = Encoding.ASCII.GetString(myDataBuffer);

                }
                catch (Exception ex)
                {
                    lcHtml = ex.Message;
                    isRefreshingCache = false;
                    ErrHandler.WriteError(ex.Message + "\n" + 
                        ex.StackTrace.ToString());
                    LogUtil.LogDebugMessages(ex.Message + ":" + 
                        ex.StackTrace.ToString());
                }
                isRefreshingCache = false;
            }



            MailMessage mail = new MailMessage(
                new MailAddress("jgiblin@univision.net"), 
                new MailAddress("jgiblin@univision.net"));
            mail.Subject = "Cache Expire: " + key;
            mail.Body = string.Format("The Key {0} has expired at {1}", 
                key, DateTime.Now.ToShortDateString() + " " +
                DateTime.Now.ToShortTimeString()) + "\nRefreshing Cache: " + 
                lcHtml;
            SmtpClient smtp = new SmtpClient("mercury.utg.uvn.net");
            mail.IsBodyHtml = false;
            try
            {

                smtp.Send(mail);

            }
            catch (Exception ex)
            {
                ErrHandler.WriteError(ex.Message + "\n" + 
                    ex.StackTrace.ToString());
                LogUtil.LogDebugMessages(ex.Message + ":" + 
                    ex.StackTrace.ToString());
            }

        }
    }

for some reason, when I go to the page. Someone times the data is cached and sometimes it is not. Is there something wrong here

I tried app fabric but since the server does not have iis 7 I am not able to use that

casperOne
  • 73,706
  • 19
  • 184
  • 253
H20rider
  • 2,162
  • 5
  • 29
  • 47
  • Are you sure that you are not restarting the appdomain between visits (i.e. hitting F5 to debug would clear your cache). – Paddy Mar 14 '11 at 14:15
  • Just some advice, I think you could improve this by not intertwining your application code with the cache manager. The CacheManager should just get/set key/values in whatever underlying caching system you use (redis, other). In your existing business logic where you would for example fetch a user, you check the cache, if it's null you retrieve from database, put in cache and then return item. If the cache did contain the user then you just return the user from cache and skip your database query. – The Muffin Man Nov 18 '15 at 18:25

2 Answers2

0

The amount of data you can get into the cache may be the issue.

If the cache is full then the data will obviously not be cached.

You can check your memory allocation using the process monitor, have a look in "Cache Total Entries."

Joe Ratzer
  • 18,176
  • 3
  • 37
  • 51
  • how do I check this. I couldnt find anything – H20rider Mar 14 '11 at 17:55
  • Check this out - http://msdn.microsoft.com/en-us/library/ms972959.aspx#monitor_perf_topic9 It should help – Joe Ratzer Mar 15 '11 at 13:01
  • thanks. I think I have an idea of why I am loosing my cache. I looked in the event viewer and saw that I had a .net 4 Stack overflow. I am still trying to figure out that issue. – H20rider Mar 18 '11 at 13:14
  • Glad I could help, I hope you went on to solve it. If I've helped can you accept the answer and/or vote it up. If you accept answers you're more likely to get help from the community next time. Cheers. – Joe Ratzer Mar 22 '11 at 08:45
0

Looks to me like you may have a race condition in your RefreshCache call. Check out this great answer for suggestions on how to handle synchronization:

C# version of java's synchronized keyword?

If I were you, I'd simplify my code. You only really need:

  1. when the application starts up, load the cache
  2. when the cache expires, reload it
  3. if a user tries to access the cached object and misses, sleep their thread for a second and check again
Community
  • 1
  • 1
Milimetric
  • 13,411
  • 4
  • 44
  • 56
  • I dont think it is a synchronization issue. The items do get cached initially but the problem is it does not remain in cache that long. I set the timeout to 24 hours and still expires in an hour. I alos tried to use the – H20rider Mar 15 '11 at 22:50