详解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(, , ));//30分钟过期
return fullName;
}
MemoryCacheHelper的方法GetCacheItem里面的Func<T>我使用了一个匿名函数用来获取缓存的值。
delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); }
而调用BLLFactory<User>.Instance.GetFullNameByID则是从数据库里面获取对应的数据了。
这样在第一次或者缓存过期的时候,自动调用业务对象类的方法来获取数据了。
最后,在界面上调用GetUserFullName的方法即可实现基于缓存方式的调用,程序第一次使用的,碰到指定的键没有数据,就去数据库里面获取,以后碰到该键,则直接获取缓存的数据了。
下面图形是程序具体的实现效果。
当然,以上两种方式都还可以通过AOP的注入方式实现代码的简化操作,不过由于对AOP的引入,会涉及到更多的知识点,而且熟悉程序还不够,所以依然采用较为常用的方式来处理缓存的数据。
详解Winform里面的缓存使用的更多相关文章
- 小白如何学习PyTorch】25 Keras的API详解(下)缓存激活,内存输出,并发解决
[新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.时间序列等多个目标为技术学习的分群和水群唠嗑答疑解惑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx6450 ...
- Orchard详解--第四篇 缓存介绍
Orchard提供了多级缓存支持,它们分别是: 1. 应用程序配置级缓存ICacheManager: 它用来存储应用程序的配置信息并且可以提供一组可扩展的参数来处理缓存过期问题,在Orchard中默认 ...
- 详解PHP操作Memcache缓存技术提高响应速度的方法
本文转载http://blog.csdn.net/zhihua_w 不错的博客,仅供本人学习之用 一般来说,如果并发量不大的情况,使不使用缓存技术并没有什么影响,但如果高并发的情况,使用缓存技术就显 ...
- MyBatis 一级缓存、二级缓存全详解(一)
目录 MyBatis 一级缓存.二级缓存全详解(一) 什么是缓存 什么是MyBatis中的缓存 MyBatis 中的一级缓存 初探一级缓存 探究一级缓存是如何失效的 一级缓存原理探究 还有其他要补充的 ...
- Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解
转载:http://freeloda.blog.51cto.com/2033581/1288553 大纲 一.前言 二.环境准备 三.安装与配置Nginx 四.Nginx之反向代理 五.Nginx之负 ...
- (转载)详解网络传输中的三张表,MAC地址表、ARP缓存表以及路由表
郑重声明:原文转载于http://dengqi.blog.51cto.com/5685776/1223132 向好文章致敬!!! 一:MAC地址表详解 说到MAC地址表,就不得不说一下交换机的工作原理 ...
- Android图片缓存之Bitmap详解
前言: 最近准备研究一下图片缓存框架,基于这个想法觉得还是先了解有关图片缓存的基础知识,今天重点学习一下Bitmap.BitmapFactory这两个类. 图片缓存相关博客地址: Android图片缓 ...
- Memcached集群/分布式/高可用 及 Magent缓存代理搭建过程 详解
当网站访问量达到一定时,如何做Memcached集群,又如何高可用,是接下来要讨论的问题. 有这么一段文字来描述“Memcached集群” Memcached如何处理容错的? 不处理!:) 在memc ...
- 浏览器 HTTP 协议缓存机制详解
最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里带了 etag, ...
随机推荐
- MySQL中自己不太常用的命令
一 更改表的信息 alter table students add primary key (stunum); 为已经创建好的表添加主键. alter语句不仅可以添加主键,还可以对已经创建好的表修改一 ...
- js页面跳转参考代码大全
整理一下JS页面跳转参考代码 第一种: <script language=/"javascript/" type=/"text/javascript/&qu ...
- C# 通过自定义特性 实现根据实体类自动创建数据库表
.Net新手通常容易把属性(Property)跟特性(Attribute)搞混,其实这是两种不同的东西 属性指的类中封装的数据字段:而特性是对类.字段.方法和属性等元素标注的声明性信息 如下代码(Id ...
- Aspose.Words.Tables.Row类操作word表格行
http://www.aspose.com/docs/display/wordsnet/Aspose.Words.Tables.Row+Class Retrieves the index of a r ...
- 具有timeout 功能的函数调用
做项目的时候有时经常会需要一个带有timeout功能的函数调用. 比如从后台读数据并期望在给定时间内返回.借此机会包装了一个简单的C# class, 直接上代码吧. public class Time ...
- Studio for WPF:使用 C1TileView 创建图片库
C1TileView 提供了数据交互浏览的功能.允许我们设置最大化和最小化浏览模板,我们可以通过最小化模板快速定位详细浏览选项. 下面我们分步分享实现方法: 1.添加 C1TileView 到窗体,并 ...
- Ajax基础实例
前端代码 <script type="text/javascript"> var xmlhttp; function go(url) { xmlhttp=null; i ...
- [翻译]:SQL死锁-锁与事务级别
其实这一篇呢与解决我项目中遇到的问题也是必不可少的.上一篇讲到了各种锁之间的兼容性,里面有一项就是共享锁会引起死锁,如何避免呢,将我们的查询都设置中read uncommitted是否可行呢?其结果显 ...
- Android笔记——Windows环境下Android Studio v1.0安装教程
本文主要讲解Windows环境下Android Studio的安装教程,Mac的Android Studio安装与此类似不在赘述,另外友情提示Windows下的SDK与Mac的SDK是通用的,可以直接 ...
- [js开源组件开发]js手机端浮层控件,并有多种弹出小提示,兼容pc端浏览器
js dialog组件,包含alert和confirm的实现 本组件所有的资源均在github上可以查看源代码 GitHub 本dialog的组件的例子请在这里查看 demo dialog js di ...