none
MemoryCache使用的问题

    问题

  • 我在服务器端想用MemoryCache做一个缓存。

    首先简单包了下:

            

        public class GlobalCache
        {
            private ObjectCache _Cache = null;
            //private static GlobalCache _GlobalCache = null;


            public GlobalCache()
            {
                _Cache = MemoryCache.Default;
            }

            public static GlobalCache GetInstance()
            {
                //if (_GlobalCache == null)
                //{
                //    _GlobalCache = new GlobalCache();
                //    _GlobalCache._Cache = MemoryCache.Default;
                //}

                //return _GlobalCache;
                return new GlobalCache();
            }

            public void SetFileCache(string key, object value, CacheItemPolicy policy, ChangeMonitor moniter,string filePath)
            {
                if (policy == null)
                {
                    CacheItemPolicy defaultPolicy = new CacheItemPolicy();
                    if(moniter == null)
                    {
                        //新建一个文件监视器对象,添加对资源文件的监视
                        HostFileChangeMonitor fileMoniter = new HostFileChangeMonitor(new List<string> { filePath });

                        defaultPolicy.ChangeMonitors.Add(fileMoniter);

                    }
                    else
                    {
                        defaultPolicy.ChangeMonitors.Add(moniter);
                    }
                    _Cache.Set(key, value, defaultPolicy);

                }
                else
                {
                    _Cache.Set(key, value, policy);
                }
            }

            public void SetSQLCache(string key, object value, CacheItemPolicy policy, ChangeMonitor moniter)
            {
                if (policy == null)
                {
                    CacheItemPolicy defaultPolicy = new CacheItemPolicy();
                    if (moniter == null)
                    {
                        //defaultPolicy.SlidingExpiration = TimeSpan.FromSeconds(20);
                        defaultPolicy.AbsoluteExpiration = DateTime.Now.AddSeconds(20);
                    }
                    else
                    {
                        defaultPolicy.ChangeMonitors.Add(moniter);
                    }
                    _Cache.Set(key, value, defaultPolicy);
                    WriteFile("缓存数量" + _Cache.GetCount(), @"c:\共享\log.txt");
                }
                else
                {
                    _Cache.Set(key, value, policy);
                }
            }

            /// <summary> 通过key获取缓存的对象  </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="key"></param>
            /// <returns></returns>
            public T GetCache<T>(string key)
            {
                return (T)_Cache.GetCacheItem(key).Value;
            }

            /// <summary>  判断是否有缓存对象 </summary>
            /// <param name="key">缓存对象的key</param>
            /// <returns></returns>
            public bool ContainKey(string key)
            {
                return _Cache.Contains(key);
            }
        }

    下面是我调用SetSQLCache方法来使用缓存的代码:

    //查找缓存中是否有数据
                GlobalCache cache = new GlobalCache();
                if (cache.ContainKey(CACHE_NAME) == false)
                {

                    //放入缓存中
                    cache.SetSQLCache(CACHE_NAME, dsCheck, null, null);
                    PubFunction.WriteFile("不取缓存", @"c:\共享\log.txt");
                }
                else
                {
                    //从缓存中获取
                    dsCheck = cache.GetCache<DataSet>(CACHE_NAME);
                    PubFunction.WriteFile("取缓存", @"c:\共享\log.txt");

                    //dsCheck.Tables.Add(GetBBState(vsBYNM, vsSLNM).Copy().TableName="");

                }

    根据下面的日志信息发现几次之后没法缓存数据了,怎么回事?

    /////////////第一次调用(正常)///////////////
    【Time】:2016-5-5 16:06:56
    【Para】:缓存数量1
    【Time】:2016-5-5 16:06:56
    【Para】:不取缓存
    /////////////第二次调用(20秒内走缓存正常)///////////////
    【Time】:2016-5-5 16:07:04
    【Para】:取缓存
    /////////////第三次调用(20秒以上不走缓存正常)///////////////
    【Time】:2016-5-5 16:07:36
    【Para】:缓存数量1
    【Time】:2016-5-5 16:07:36
    【Para】:不取缓存
    /////////////第三次调用(20秒以上不走缓存,但是在执行了MemoryCache的Set方法后并没有缓存上数据)///////////////
    【Time】:2016-5-5 16:07:56
    【Para】:缓存数量0
    【Time】:2016-5-5 16:07:56
    【Para】:不取缓存
    /////////////第四次调用(从第三次往后都不对了,一直缓存不上数据)///////////////
    【Time】:2016-5-5 16:11:10
    【Para】:缓存数量0
    【Time】:2016-5-5 16:11:10
    【Para】:不取缓存

    2016年5月6日 3:37

全部回复

  • 数据库的缓存,可否考虑用SqlCacheDependency

    SqlCacheDependency dependency = new SqlCacheDependency(cmd);


    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2016年5月6日 6:13
  • 数据库的缓存,可否考虑用SqlCacheDependency

    SqlCacheDependency dependency = new SqlCacheDependency(cmd);

    cmd.ExecuteNonQuery();

    如果是.NET 4,可考虑用线程安全的集合。

    参考这里


    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    SqlCacheDependency是ASP.net,我这个其实就是个纯winform的,能用么?然后其实外层框架中也包裹了数据库操作的。也不能直接使用SqlCommand了,我这里要用缓存,只是有个数据校验的过程,校验的数据一般都是字典类型的数据修改的不频繁。所以我想从第一次从数据库取出后在内存中缓存一下。之前想过用static的dictionary,但是没有清空策略想用MemoryCache是因为想通过他的相对时间策略,指定一段时间不操作该缓存对象的时候清空这个缓存(上面的例子中我用的绝对时间做的测试),但是如果我在客户端同样用这个缓存一个xml配置文件的内容信息却又是没有问题的。但在服务端缓存一个ds时就像上面日志打印出来的样,第一次缓存清空后,后面就缓存不上了。
    2016年5月6日 7:10
  • 这里

    _Cache.Set(key, value, policy);

    加一个lock试一下

    lock(_Cache)

     _Cache.Set(key, value, policy);

    还有一个地方可能是

     public class GlobalCache 这个要用单件模式,确保整个程序只有一份实例

    改成

    private GlobalCache()
            {
                _Cache = MemoryCache.Default;
            }


    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2016年5月6日 9:03
  • 这里

    _Cache.Set(key, value, policy);

    加一个lock试一下

    lock(_Cache)

     _Cache.Set(key, value, policy);

    还有一个地方可能是

     public class GlobalCache 这个要用单件模式,确保整个程序只有一份实例

    改成

    private GlobalCache()
            {
                _Cache = MemoryCache.Default;
            }


    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    试了下lock,还是没起作用,最开始用的单例模式,不起作用又改成了这样的。并且MemoryCache.Default内部本来就是用的单例模式,所以我这里就没用了。我试了试,我添加一个缓存后 _Cache.Set("123", "测试", new CacheItemPolicy() { Priority = CacheItemPriority.NotRemovable });  即使不设置清除策略过一会儿后还是莫名其妙的丢失了。难道跟服务器的某些设置有关?
    2016年5月9日 0:41
  • 是不是ASP.NET程序,会不会是被IIS 应用程序池(Application Pool)回收了。

    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    2016年5月10日 1:31
  • 是不是ASP.NET程序,会不会是被IIS 应用程序池(Application Pool)回收了。

    专注于.NET MIS开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms

    是ASP.net的程序。是不是被回收的了我现在也不清楚
    2016年5月10日 11:05