在前一篇烂文中,老周简单讲述了非Web应用的缓存技术的基本用法。其实嘛,使用系统默认方案已经满足我们的需求了,不过,如果你真想自己来配置缓存,也是可以的。
缓存的自定义配置可以有两种方案,一种是用代码在应用程序中配置,即实例化MemoryCache对象时,可以向构造函数传递一个NameValueCollection实例,数据结构就是key-value形式,这些配置项的名字其实就是MemoryCacheElement类的以下三个属性:CacheMemoryLimitMegabytes、PhysicalMemoryLimitPercentage、PollingInterval。
老周不那么推荐上面的方案,倒是下面的方案较灵活。第二种方案就是使用配置文件(App.config),这种方法方便修改,而且不必动不动就重新编译。所以,本文就采取第二种方案。
自定义缓存配置需要指定名字,因为你可能会配置多个模式,每个模式都给一个命名,名字你可以随便用,但不要用Default,因为这个是系统默认保留的。
下面我们来配置一个名为cat的缓存设置。
<configuration> <system.runtime.caching> <memoryCache> <namedCaches> <add name="cat" cacheMemoryLimitMegabytes="1" pollingInterval="00:01:00" physicalMemoryLimitPercentage="5"/> </namedCaches> </memoryCache> </system.runtime.caching> </configuration>
这个和配置数据库的连接字符串(connectionString)有点像,namedCaches下面每一个add子元素就是一个缓存配置项,必须用name来指定该项的名字,cacheMemoryLimitMegabytes用于限制缓存占用内存的大小,单位是MB,我这里配置为1 Mb。
physicalMemoryLimitPercentage则是限制缓存占用物理内存的百分比,值为0到100,包括0和100,如果为0,表示由系统自动调配,如果物理内存紧张,会清理缓存。
pollingInterval表示检查缓存限制的时间间隔,格式为00:00:00,即时-分-秒格式,我这里设置为1分钟。这个值不要设置得太频繁,要是设置为1秒钟就太吃性能了,没有这个必要,放宽到5分钟,10分钟也无妨,因为只是检查一下当前缓存占用的空间是否超出前面设定的两个限制值。比如每隔1分钟检查一下缓存大小是否超出物理内存的5%的容量。
如果想在配置前清除以前的配置,可以在add元素前加上clear元素;如果想删除某个已有的配置(可能在machine.config中有配置,一般不应该修改它,尤其是你不熟悉的情况下),可以在add元素前使用remove元素。与连接字符串的配置方法差不多。
配置完成后,就可以在代码中应用这些配置了。
在实例化MemoryCache时,向构造函数传递配置项的名字,比如我上面的示例,定义的配置名为cat。如果MemoryCache在配置文件中找不到指定名字的项,就会自动套用默认值。
请看示例代码:
// 注意: // 名称引用配置文件中定义的名字 // 如果找不到,就会填充默认值 cache = new MemoryCache("cat"); //实例化 // 输出调试信息 System.Diagnostics.Debug.WriteLine("MemoryCache 实例的属性:\n" + $"{nameof(MemoryCache.Name)} = {cache.Name}\n" + $"{nameof(MemoryCache.CacheMemoryLimit)} = {cache.CacheMemoryLimit / 1024 / 1024} Mb\n" + $"{nameof(MemoryCache.PhysicalMemoryLimit)} = {cache.PhysicalMemoryLimit} %\n" + $"{nameof(MemoryCache.PollingInterval)} = {cache.PollingInterval:t}");
如果你在配置文件中配置的项名为dog,这里你就把dog传递给MemoryCache的构造函数,我这里是cat。
我还用Debug类输出了调试信息,以便在调试运行时输出内容,从而验证配置文件中的缓存配置是否被正确使用。如下图。
这个输出表明,刚刚的配置已被正确使用了。
下面我们就可以往缓存里面读写数据了。
if (cache.Contains("item")) { int v = Convert.ToInt32(cache["item"]); //读缓存 label1.Text = v.ToString(); } else { int v = rand.Next(0, 1000); //生成随机数 // 写入缓存 cache.Set("item", v, DateTimeOffset.Now.AddSeconds(5)); label1.Text = v.ToString(); }
这里我就把一个随机生成的整数值存入缓存,过期时间为5秒钟之后。
运行应用程序,只要在5秒钟内点击按钮,界面上显示的数字就不会变,因为5秒钟内,它读的是缓存中的内容。当超过5秒钟后再点击按钮,就会更新为新的值。
由于MemoryCache类实现了IDisposable接口,所以,当不再需要使用缓存时,应该调用Dispose方法释放相关资源。
cache?.Dispose(); //释放资源 cache = null;
好了,本文的牛逼就吹到这里。