详解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的引入,会涉及到更多的知识点,而且熟悉程序还不够,所以依然采用较为常用的方式来处理缓存的数据。

(0)

相关推荐

  • c#自带缓存使用方法 c#移除清理缓存

    复制代码 代码如下: /// <summary>/// 获取数据缓存/// </summary>/// <param name="CacheKey">键</param>public static object GetCache(string CacheKey){    System.Web.Caching.Cache objCache = HttpRuntime.Cache;    return objCache[CacheKey];}/

  • asp.net(C#)遍历memcached缓存对象

    STATS命令 遍历memcached缓存对象(C#)转载之青草堂 出于性能考虑,memcached没有提供遍历功能,不过我们可以通过以下两个stats命令得到所有的缓存对象. 1.stats items 显示各个slab中item的数目. 2.stats cachedump slab_id limit_num 显示某个slab中的前limit_num个key列表,显示格式:ITEM key_name [ value_length b; expire_time|access_time s] 除了

  • C#自定义缓存封装类实例

    本文实例讲述了C#自定义缓存封装类.分享给大家供大家参考.具体如下: 这个自定义的C#类封装了部分常用的缓存操作,包括写入缓存,读取缓存,设置缓存过期时间等等,简化了C#的缓存操作,代码非常简单,易于阅读. using System; using System.Web; namespace DotNet.Utilities { /// <summary> /// 缓存相关的操作类 /// </summary> public class DataCache { /// <sum

  • C# Memcached缓存用法实例详解

    本文实例讲述了C#中Memcached缓存的用法,分享给大家供大家参考.具体方法如下: ICacheStrategy.cs文件如下: 复制代码 代码如下: public interface ICacheStrategy {         /// <summary>         /// 添加数据到缓存         /// </summary>         /// <param name="objId">缓存名称</param>

  • C# memcached缓存使用实例代码

    复制代码 代码如下: public interface ICacheStrategy    {        /// <summary>        /// 添加数据到缓存        /// </summary>        /// <param name="objId">缓存名称</param>        /// <param name="o">缓存内容</param>      

  • C#实现清除IE浏览器缓存的方法

    本文实例讲述了C#实现清除IE浏览器缓存的方法.分享给大家供大家参考.具体如下: 项目中碰到wpf webbrowser的几个问题,在此记录一下 1.webbrowser中对于jquery的bind事件的处理. 在普通的浏览器下一下这种写法没有任何问题 var content = $("<div><h4><span>" + category_name + "</span>(<a id='href_" + guid

  • winform简单缓存类实例

    本文实例讲述了winform简单缓存类.分享给大家供大家参考.具体如下: public partial class Form3 : Form { //缓存类 System.Web.Caching.Cache cache; public Form3() { InitializeComponent(); string SQL = "select top 1000 * from infomation"; DataTable datatable = DBHelper.GetDataTable(

  • C#中缓存的基本用法总结

    本文初步探讨了C#缓存的原理及应用,并以实例加以分析总结,这些对C#初学者来说是很有必要熟练掌握的内容.具体如下: 一.概述: 缓存应用目的:缓存主要是为了提高数据的读取速度.因为服务器和应用客户端之间存在着流量的瓶颈,所以读取大容量数据时,使用缓存来直接为客户端服务,可以减少客户端与服务器端的数据交互,从而大大提高程序的性能. 1.缓存的引用空间:System.Web.Caching; 缓存命名空间主要提供三种操作:缓存数据对象.对象的缓存依赖和数据库的缓存依赖.其中缓存任何对象都使用一个类C

  • C#函数式编程中的缓存技术详解

    缓存技术 该节我们将分成两部分来讲解,第一部分为预计算,第二部分则为缓存.缓存这个技术对应从事开发的人员来说是非常熟悉的,从页面缓存到数据库缓存无处不在,而其最重要的特点就是在第一次查询后将数据缓存,在以后的查询过程中就无需重新计算而直接从内存中将结果返回,大大提高了性能,而我们这里的缓存则集中运用在函数上.  预计算 可能一些人并不能立马理解这个词的含义,所以我们就简单的从生活例子出发介绍一下.很多人在工作中一定会这样做事,比如上级吩咐了你一件事,但是这件事的后半部分要等另一个同事做好之后把对

  • 在WCF数据访问中使用缓存提高Winform字段中文显示速度的方法

    本文较为详细的讲述了在WCF数据访问中使用缓存提高Winform字段中文显示速度的方法,分享给大家供大家参考之用.具体方法如下: 在我们开发基于WCF访问方式的Winform程序的时候,一般情况下需要对界面显示的字段进行中文显示的解析.如果是硬编码进行中文显示,那么除了不方便调整及代码臃肿外,性能上没有什么问题,但是不建议这样处理:一般情况下,我们把中文对照信息放到业务类里面去统一解析,但是这样会导致每次WCF访问方式请求解析中文化的操作耗费一定的响应时间.如果使用缓存存储中文字段的对照表,那么

随机推荐