详解Winform里面的缓存使用

缓存在很多情况下需要用到,合理利用缓存可以一方面可以提高程序的响应速度,同时可以减少对特定资源访问的压力。本文主要针对自己在Winform 方面的缓存使用做一个引导性的介绍,希望大家能够从中了解一些缓存的使用场景和使用方法。缓存是一个中大型系统所必须考虑的问题。为了避免每次请求都去访 问后台的资源(例如数据库),我们一般会考虑将一些更新不是很频繁的,可以重用的数据,通过一定的方式临时地保存起来,后续的请求根据情况可以直接访问这 些保存起来的数据。这种机制就是所谓的缓存机制。

.NET 4.0的缓存功能主要由三部分组成:System.Runtime.Caching,System.Web.Caching.Cache和Output Cache。

System.Runtime.Caching这是在.NET 4.0中新增的缓存框架,主要是使用MemoryCache对象,该对象存在于程序集System.Runtime.Caching.dll。

System.Web.Caching.Cache这个则是在.NET2.0开始就一直存在的缓存对象,一般主要用在Web中,当然也可以用于Winform里面,不过要引用System.Web.dll。

Output Cache则是Asp.NET里面使用的,在ASP.NET 4.0之前的版本都是直接使用System.Web.Caching.Cache来缓存HTML片段。在ASP.NET 4.0中对它进行了重新设计,提供了一个OutputCacheProvider供开发人员进行扩展,但是它默认情况下,仍然使用 System.Web.Caching.Cache来做做缓存。

1、自定义Hastable的缓存处理。
除了上面三种的缓存机制,一般我们还可以在静态对象里面通过HashTable或者Dictionary的方式进行自定义的缓存存储和使用。

例如我在我自己所开发的程序里面,都使用了工厂类来创建业务对象,由于创建业务对象以及数据访问层对象,是一个在界面或者中间层反复调用的操作,因 此需要把经常调用的对象把它存储起来,下载调用的时候,直接从内存中取出来即可。如下面的BLLFactory类,就是一个基于泛型对象的业务类的创建操 作,使用了基于Hashtable的静态对象进行缓存处理。

/// <summary>
    /// 对业务类进行构造的工厂类
    /// </summary>
    /// <typeparam name="T">业务对象类型</typeparam>
    public class BLLFactory<T> where T : class
    {
        private static Hashtable objCache = new Hashtable();
        private static object syncRoot = new Object();
         /// <summary>
        /// 创建或者从缓存中获取对应业务类的实例
        /// </summary>
        public static T Instance
        {
            get
            {
                string CacheKey = typeof(T).FullName;
                T bll = (T)objCache[CacheKey];  //从缓存读取
                if (bll == null)
                {
                    lock (syncRoot)
                    {
                        if (bll == null)
                        {
                            bll = Reflect<T>.Create(typeof(T).FullName, typeof(T).Assembly.GetName().Name); //反射创建,并缓存
                            objCache.Add(typeof(T).FullName, bll);
                        }
                    }
                }
                return bll;
            }
        }
    }

2、使用.NET4.0的MemoryCache对象实现缓存

MemoryCache的使用网上介绍的不多,不过这个是.NET4.0新引入的缓存对象,估计主要是替换原来企业库的缓存模块,使得.NET的缓存可以无处不在,而不用基于特定的Windows版本上使用。

首先我们使用来创建一个基于MemoryCache的辅助类MemoryCacheHelper,方便调用进行缓存处理。

/// <summary>
    /// 基于MemoryCache的缓存辅助类
    /// </summary>
    public static class MemoryCacheHelper
    {
        private static readonly Object _locker = new object();

        public static T GetCacheItem<T>(String key, Func<T> cachePopulate, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
        {
            if(String.IsNullOrWhiteSpace(key)) throw new ArgumentException("Invalid cache key");
            if(cachePopulate == null) throw new ArgumentNullException("cachePopulate");
            if(slidingExpiration == null && absoluteExpiration == null) throw new ArgumentException("Either a sliding expiration or absolute must be provided");

            if(MemoryCache.Default[key] == null)
            {
                lock(_locker)
                {
                    if(MemoryCache.Default[key] == null)
                    {
                        var item = new CacheItem(key, cachePopulate());
                        var policy = CreatePolicy(slidingExpiration, absoluteExpiration);

                        MemoryCache.Default.Add(item, policy);
                    }
                }
            }

            return (T)MemoryCache.Default[key];
        }

        private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
        {
            var policy = new CacheItemPolicy();

            if(absoluteExpiration.HasValue)
            {
                policy.AbsoluteExpiration = absoluteExpiration.Value;
            }
            else if(slidingExpiration.HasValue)
            {
                policy.SlidingExpiration = slidingExpiration.Value;
            }

            policy.Priority = CacheItemPriority.Default;

            return policy;
        }
    }

这个辅助类只有一个public方法,就是GetCacheItem,使用的时候,需要指定key和获取数据的处理代理,还有缓存的过期时间,是基于TimeSpan的还是基于绝对时间的,选择其一。

上面的辅助类,我们在什么情况下会使用到呢?

假如在一个工作流模块中用到了人员ID,而人员ID需要进行人员名称的转义,人员信息我们一般知道放在权限系统模块里面,那么如果在工作流里面需要频繁对人员ID进行转义,那么就需要方法调用权限系统的接口模块,这样处理就可以使用缓存模块进行优化处理的了。

void gridView1_CustomColumnDisplayText(object sender, DevExpress.XtraGrid.Views.Base.CustomColumnDisplayTextEventArgs e)
        {
            if (e.Column.FieldName.Equals("ProcUser") || e.Column.FieldName.Equals("ProcUid") || e.Column.FieldName.Equals("UserId"))
            {
                if (e.Value != null)
                {
                    e.DisplayText = SecurityHelper.GetUserFullName(e.Value.ToString());
                }
            }
        }

其中的SecurityHelper.GetUserFullName是我对调用进行基于缓存的二次封装,具体逻辑如下所示。

/// <summary>
        /// 根据用户的ID,获取用户的全名,并放到缓存里面
        /// </summary>
        /// <param name="userId">用户的ID</param>
        /// <returns></returns>
        public static string GetUserFullName(string userId)
        {
            string key = "Security_UserFullName" + userId;
            string fullName = MemoryCacheHelper.GetCacheItem<string>(key,
                delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); },
                new TimeSpan(0, 30, 0));//30分钟过期
            return fullName;
        }

MemoryCacheHelper的方法GetCacheItem里面的Func<T>我使用了一个匿名函数用来获取缓存的值。

delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); }

而调用BLLFactory<User>.Instance.GetFullNameByID则是从数据库里面获取对应的数据了。

这样在第一次或者缓存过期的时候,自动调用业务对象类的方法来获取数据了。

最后,在界面上调用GetUserFullName的方法即可实现基于缓存方式的调用,程序第一次使用的,碰到指定的键没有数据,就去数据库里面获取,以后碰到该键,则直接获取缓存的数据了。

下面图形是程序具体的实现效果。

当然,以上两种方式都还可以通过AOP的注入方式实现代码的简化操作,不过由于对AOP的引入,会涉及到更多的知识点,而且熟悉程序还不够,所以依然采用较为常用的方式来处理缓存的数据。

时间: 2024-08-13 11:43:01

详解Winform里面的缓存使用的相关文章

iOS疯狂详解之AFNetworking图片缓存问题

AFNetworking网络库已经提供了很好的图片缓存机制,效率是比较高的,但是我发现没有直接提供清除缓存的功能,可项目通常都需要添加 清除功能的功能,因此,在这里我以UIImageView+AFNetworking类中添加了下面一个清除功能方法: + (void)clearCache; + (void)clearCache { AFImageCache *cache = (AFImageCache *)[UIImageView sharedImageCache]; [cache removeA

MySQL详解(21)------------缓存参数优化

数据库属于 IO 密集型的应用程序,其主要职责就是数据的管理及存储工作.而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个IO是在毫秒级别,二者相差3个数量级.所以,要优化数据库,首先第一步需要优化的就是 IO,尽可能将磁盘IO转化为内存IO.本文先从 MySQL 数据库IO相关参数(缓存参数)的角度来看看可以通过哪些参数进行IO优化: query_cache_size/query_cache_type (global) Query cache 作用于整个 MySQL

linux下find(文件查找)命令的详解

文件查找命令locate和find详解 locate 配合数据库缓存,快速查看文件位置,非实时查找( 数据库查找) find 实际搜寻硬盘查询文件名称 ,实时查找 locate简介 locate命令其实是find -name的另一种写法,但是要比后者快得多,原因在于它不搜索具体目录,而是搜索一个数据库/var/lib/locatedb,这个数据库中含有本地所有文件信息.Linux系统自动创建这个数据库,并且每天自动更新一次,所以使用locate命令查不到最新变动过的文件.为了避免这种情况,可以在

Android:ViewPager扩展详解——带有导航的ViewPagerIndicator(附带图片缓存,异步加载图片)

大家都用过viewpager了, github上有对viewpager进行扩展,导航风格更加丰富,这个开源项目是ViewPagerIndicator,很好用,但是例子比较简单,实际用起来要进行很多扩展,比如在fragment里进行图片缓存和图片异步加载. 下面是ViewPagerIndicator源码运行后的效果,大家也都看过了,我多此一举截几张图: 下载源码请点击这里 ===========================================华丽的分割线==============

Nginx反向代理、负载均衡、页面缓存、URL重写及读写分离详解

大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负载均衡 六.Nginx之页面缓存 七.Nginx之URL重写 八.Nginx之读写分离 注,操作系统为 CentOS 6.4 x86_64 , Nginx 是版本是最新版的1.4.2,所以实验用到的软件请点击这里下载:http://yunpan.cn/QXIgqMmVmuZrm 一.前言 在前面的几篇博文中我们主要讲解了Nginx作为Web服务器知识点,主要的知识点有nginx的理论详解.ngin

浏览器缓存机制详解

对于浏览器缓存,相信很多开发者对它真的是又爱又恨.一方面极大地提升了用户体验,而另一方面有时会因为读取了缓存而展示了"错误"的东西,而在开发过程中千方百计地想把缓存禁掉.那么浏览器缓存究竟是个什么样的神奇玩意呢? 什么是浏览器缓存: 简单来说,浏览器缓存就是把一个已经请求过的Web资源(如html页面,图片,js,数据等)拷贝一份副本储存在浏览器中.缓存会根据进来的请求保存输出内容的副本.当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是

(转载)详解网络传输中的三张表,MAC地址表、ARP缓存表以及路由表

郑重声明:原文转载于http://dengqi.blog.51cto.com/5685776/1223132 向好文章致敬!!! 一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理了,因为交换机是根据MAC地址表转发数据帧的.在交换机中有一张记录着局域网主机MAC地址与交换机接口的对应关系的表,交换机就是根据这张表负责将数据帧传输到指定的主机上的. 交换机的工作原理 交换机在接收到数据帧以后,首先.会记录数据帧中的源MAC地址和对应的接口到MAC表中,接着.会检查自己的MAC

Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解

大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负载均衡 六.Nginx之页面缓存 七.Nginx之URL重写 八.Nginx之读写分离 注,操作系统为 CentOS 6.4 x86_64 , Nginx 是版本是最新版的1.4.2,所以实验用到的软件请点击这里下载:http://yunpan.cn/QXIgqMmVmuZrm 一.前言 在前面的几篇博文中我们主要讲解了Nginx作为Web服务器知识点,主要的知识点有nginx的理论详解.ngin

[转]hibernate缓存机制所有详解

以下文章来自http://www.blogjava.net/tbwshc/articles/380013.html Hibernate 所有缓存机制详解 hibernate提供的一级缓存 hibernate是一个线程对应一个session,一个线程可以看成一个用户.也就是说session级缓存(一级缓存)只能给一个线程用,别的线程用不了,一级缓存就是和线程绑定了. hibernate一级缓存生命周期很短,和session生命周期一样,一级缓存也称session级的缓存或事务级缓存.如果tb事务提