詳解Winform里面的緩存使用
緩存在很多情況下需要用到,合理利用緩存可以一方面可以提高程序的響應(yīng)速度,同時(shí)可以減少對(duì)特定資源訪問(wèn)的壓力。本文主要針對(duì)自己在Winform方面的緩存使用做一個(gè)引導(dǎo)性的介紹,希望大家能夠從中了解一些緩存的使用場(chǎng)景和使用方法。緩存是一個(gè)中大型系統(tǒng)所必須考慮的問(wèn)題。為了避免每次請(qǐng)求都去訪問(wèn)后臺(tái)的資源(例如數(shù)據(jù)庫(kù)),我們一般會(huì)考慮將一些更新不是很頻繁的,可以重用的數(shù)據(jù),通過(guò)一定的方式臨時(shí)地保存起來(lái),后續(xù)的請(qǐng)求根據(jù)情況可以直接訪問(wèn)這些保存起來(lái)的數(shù)據(jù)。這種機(jī)制就是所謂的緩存機(jī)制。
.NET 4.0的緩存功能主要由三部分組成:System.Runtime.Caching,System.Web.Caching.Cache和Output Cache。
System.Runtime.Caching這是在.NET 4.0中新增的緩存框架,主要是使用MemoryCache對(duì)象,該對(duì)象存在于程序集System.Runtime.Caching.dll。
System.Web.Caching.Cache這個(gè)則是在.NET2.0開始就一直存在的緩存對(duì)象,一般主要用在Web中,當(dāng)然也可以用于Winform里面,不過(guò)要引用System.Web.dll。
Output Cache則是Asp.NET里面使用的,在ASP.NET 4.0之前的版本都是直接使用System.Web.Caching.Cache來(lái)緩存HTML片段。在ASP.NET 4.0中對(duì)它進(jìn)行了重新設(shè)計(jì),提供了一個(gè)OutputCacheProvider供開發(fā)人員進(jìn)行擴(kuò)展,但是它默認(rèn)情況下,仍然使用System.Web.Caching.Cache來(lái)做做緩存。
1、自定義Hastable的緩存處理。
除了上面三種的緩存機(jī)制,一般我們還可以在靜態(tài)對(duì)象里面通過(guò)HashTable或者Dictionary的方式進(jìn)行自定義的緩存存儲(chǔ)和使用。
例如我在我自己所開發(fā)的程序里面,都使用了工廠類來(lái)創(chuàng)建業(yè)務(wù)對(duì)象,由于創(chuàng)建業(yè)務(wù)對(duì)象以及數(shù)據(jù)訪問(wèn)層對(duì)象,是一個(gè)在界面或者中間層反復(fù)調(diào)用的操作,因此需要把經(jīng)常調(diào)用的對(duì)象把它存儲(chǔ)起來(lái),下載調(diào)用的時(shí)候,直接從內(nèi)存中取出來(lái)即可。如下面的BLLFactory類,就是一個(gè)基于泛型對(duì)象的業(yè)務(wù)類的創(chuàng)建操作,使用了基于Hashtable的靜態(tài)對(duì)象進(jìn)行緩存處理。
/// <summary>
/// 對(duì)業(yè)務(wù)類進(jìn)行構(gòu)造的工廠類
/// </summary>
/// <typeparam name="T">業(yè)務(wù)對(duì)象類型</typeparam>
public class BLLFactory<T> where T : class
{
private static Hashtable objCache = new Hashtable();
private static object syncRoot = new Object();
/// <summary>
/// 創(chuàng)建或者從緩存中獲取對(duì)應(yīng)業(yè)務(wù)類的實(shí)例
/// </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); //反射創(chuàng)建,并緩存
objCache.Add(typeof(T).FullName, bll);
}
}
}
return bll;
}
}
}
2、使用.NET4.0的MemoryCache對(duì)象實(shí)現(xiàn)緩存
MemoryCache的使用網(wǎng)上介紹的不多,不過(guò)這個(gè)是.NET4.0新引入的緩存對(duì)象,估計(jì)主要是替換原來(lái)企業(yè)庫(kù)的緩存模塊,使得.NET的緩存可以無(wú)處不在,而不用基于特定的Windows版本上使用。
首先我們使用來(lái)創(chuàng)建一個(gè)基于MemoryCache的輔助類MemoryCacheHelper,方便調(diào)用進(jìn)行緩存處理。
/// <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;
}
}
這個(gè)輔助類只有一個(gè)public方法,就是GetCacheItem,使用的時(shí)候,需要指定key和獲取數(shù)據(jù)的處理代理,還有緩存的過(guò)期時(shí)間,是基于TimeSpan的還是基于絕對(duì)時(shí)間的,選擇其一。
上面的輔助類,我們?cè)谑裁辞闆r下會(huì)使用到呢?
假如在一個(gè)工作流模塊中用到了人員ID,而人員ID需要進(jìn)行人員名稱的轉(zhuǎn)義,人員信息我們一般知道放在權(quán)限系統(tǒng)模塊里面,那么如果在工作流里面需要頻繁對(duì)人員ID進(jìn)行轉(zhuǎn)義,那么就需要方法調(diào)用權(quán)限系統(tǒng)的接口模塊,這樣處理就可以使用緩存模塊進(jìn)行優(yōu)化處理的了。
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是我對(duì)調(diào)用進(jìn)行基于緩存的二次封裝,具體邏輯如下所示。
/// <summary>
/// 根據(jù)用戶的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分鐘過(guò)期
return fullName;
}
MemoryCacheHelper的方法GetCacheItem里面的Func<T>我使用了一個(gè)匿名函數(shù)用來(lái)獲取緩存的值。
delegate() { return BLLFactory<User>.Instance.GetFullNameByID(userId.ToInt32()); }
而調(diào)用BLLFactory<User>.Instance.GetFullNameByID則是從數(shù)據(jù)庫(kù)里面獲取對(duì)應(yīng)的數(shù)據(jù)了。
這樣在第一次或者緩存過(guò)期的時(shí)候,自動(dòng)調(diào)用業(yè)務(wù)對(duì)象類的方法來(lái)獲取數(shù)據(jù)了。
最后,在界面上調(diào)用GetUserFullName的方法即可實(shí)現(xiàn)基于緩存方式的調(diào)用,程序第一次使用的,碰到指定的鍵沒(méi)有數(shù)據(jù),就去數(shù)據(jù)庫(kù)里面獲取,以后碰到該鍵,則直接獲取緩存的數(shù)據(jù)了。
下面圖形是程序具體的實(shí)現(xiàn)效果。

當(dāng)然,以上兩種方式都還可以通過(guò)AOP的注入方式實(shí)現(xiàn)代碼的簡(jiǎn)化操作,不過(guò)由于對(duì)AOP的引入,會(huì)涉及到更多的知識(shí)點(diǎn),而且熟悉程序還不夠,所以依然采用較為常用的方式來(lái)處理緩存的數(shù)據(jù)。
相關(guān)文章
unity 如何獲取Text組件里text內(nèi)容的長(zhǎng)度
這篇文章主要介紹了unity 獲取Text組件里text內(nèi)容的長(zhǎng)度操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04
C#中使用快速排序按文件創(chuàng)建時(shí)間將文件排序的源碼
C#中使用快速排序按文件創(chuàng)建時(shí)間將文件排序的源碼...2007-03-03
.NET企業(yè)級(jí)項(xiàng)目中遇到的國(guó)際化問(wèn)題和解決方法
這篇文章主要介紹了.NET企業(yè)級(jí)項(xiàng)目中遇到的國(guó)際化問(wèn)題和解決方法,說(shuō)明了理國(guó)際化問(wèn)題的一些典型例子和經(jīng)驗(yàn)之談,需要的朋友可以參考下2014-07-07
WPF+ASP.NET SignalR實(shí)現(xiàn)動(dòng)態(tài)折線圖的繪制
這篇文章將以一個(gè)簡(jiǎn)單的動(dòng)態(tài)折線圖示例,簡(jiǎn)述如何通過(guò)ASP.NET SignalR實(shí)現(xiàn)后臺(tái)通知功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-01-01
C#?使用?Filestream?修改大文件指定位置數(shù)據(jù)
這篇文章主要介紹了C#?使用?Filestream修改大文件指定位置數(shù)據(jù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-09-09
詳解C#借助.NET框架中的XmlTextReader類讀取XML的方法
這篇文章主要介紹了詳解借助.NET框架中的XmlTextReader類讀取XML的方法,這種方式的執(zhí)行效率還是比較令人滿意的,需要的朋友可以參考下2016-04-04
Unity實(shí)現(xiàn)旋轉(zhuǎn)扭曲圖像特效
這篇文章主要為大家詳細(xì)介紹了Unity實(shí)現(xiàn)旋轉(zhuǎn)扭曲圖像特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02

