using System; using System.Collections.Generic; using System.Text; using System.Web.Caching; using System.Threading; namespace Ant.ORM.Cache { /// /// 全局缓存类 /// /// /// 使用示例: /// 实例化: CacheManage cache=CacheManage.Instance; /// 添加: cache.Add("路过秋天",new MDataTable); /// 判断: if(cache.Contains("路过秋天")) /// { /// 获取: MDataTable table=cache.Get("路过秋天") as MDataTable; /// } /// public class CacheManage { private readonly System.Web.HttpContext H = new System.Web.HttpContext(new System.Web.HttpRequest("Null.File", "http://cyq1162.cnblogs.com", String.Empty), new System.Web.HttpResponse(null)); private System.Web.Caching.Cache theCache = null; private Dictionary cacheState = new Dictionary(); private DateTime workTime; /// /// 缓存信息 /// public Dictionary CacheInfo { get { return cacheState; } } private CacheManage() { theCache = H.Cache; Thread thread = new Thread(new ThreadStart(ClearState)); thread.IsBackground = true; thread.Start(); workTime = DateTime.Now.AddMinutes(5); } private void ClearState() { List removeKeys = new List(); while (true) { try { Thread.Sleep(5 * 60 * 1000);//五分钟休眠时间 if (theCache.Count != cacheState.Count)//准备同步 { foreach (KeyValuePair item in cacheState) { if ((item.Value.CreaeTime.AddMinutes(4) < DateTime.Now && item.Value.CallCount < 2) || //缓存调用次数太少 item.Value.CreaeTime.AddMinutes(item.Value.CacheMinutes) < DateTime.Now)//清过期cacheState进行同步 { if (!removeKeys.Contains(item.Key)) { removeKeys.Add(item.Key); } } } foreach (string key in removeKeys) { Remove(key);//移除 } clearCount = removeKeys.Count; removeKeys.Clear(); } workTime = DateTime.Now.AddMinutes(5); } catch { System.Threading.Thread.Sleep(TimeSpan.FromHours(1)); } } } private int errorCount = 0;//缓存捕异常次数 private int clearCount = 0;//清除的缓存数 /// /// 缓存工作信息 /// public string WorkInfo { get { return string.Format("try catch error:{0}(times)--clear count:{1}--next clear work time at:{2}", errorCount, clearCount, workTime); } } /// /// 获和缓存总数 /// public int Count { get { return theCache == null ? 0 : theCache.Count; } } /// /// 返回唯一实例 /// public static CacheManage Instance { get { return Shell.instance; } } class Shell { internal static readonly CacheManage instance = new CacheManage(); } /// /// 还可用的缓存百分比 /// public long RemainMemoryPercentage { get { return theCache.EffectivePercentagePhysicalMemoryLimit; } } /// /// 还可用的缓存字节数 /// public long RemainMemoryBytes { get { return theCache.EffectivePrivateBytesLimit; } } /// /// 获得一个Cache对象 /// /// 标识 /// public object Get(string key) { if (Contains(key)) { try { cacheState[key].CallCount++; } catch { errorCount++; } return theCache[key]; } return null; } /// /// 是否存在缓存 /// /// 标识 /// public bool Contains(string key) { if (theCache[key] != null) { return true; } else { if (cacheState.ContainsKey(key)) { try { cacheState.Remove(key); } catch { errorCount++; } } return false; } } /// /// 添加一个Cache对象 /// /// 标识 /// 对象值 public void Add(string key, object value) { Add(key, value, null, 0); } public void Add(string key, object value, string filePath) { Add(key, value, filePath, 0);//再插入Cache } public void Add(string key, object value, string filePath, double cacheTimeMinutes) { if (Contains(key)) { Remove(key); } Insert(key, value, filePath, cacheTimeMinutes);//再插入Cache } /// /// 缓存设置:有则更新,无则添加 /// /// /// public void Set(string key, object value) { if (Contains(key)) { theCache[key] = value; } else { Insert(key, value, null, 0);//再插入Cache } } /// /// 更新缓存,缓存存在则更更新,不存在则跳过 /// public void Update(string key, object value) { if (Contains(key)) { theCache[key] = value; } } /// /// 相对底层Cache添加方法,添加一个Cache请用Add方法 /// /// 标识 /// 对象值 /// 文件依赖路径 /// 缓存分钟数 private void Insert(string key, object value, string filePath, double cacheTimeMinutes) { CacheDependency theCacheDependency = null; if (!string.IsNullOrEmpty(filePath)) { theCacheDependency = new CacheDependency(filePath); } double cacheTime = cacheTimeMinutes; if (cacheTimeMinutes == 0) { cacheTime = 30; } theCache.Insert(key, value == null ? string.Empty : value, theCacheDependency, DateTime.Now.AddMinutes(cacheTime), TimeSpan.Zero, CacheItemPriority.Default, null); CacheDependencyInfo info = new CacheDependencyInfo(theCacheDependency, cacheTime); if (cacheState.ContainsKey(key)) { cacheState[key] = info; } else { try { cacheState.Add(key, info); } catch { } } } /// /// 删除一个Cache对象 /// /// 标识 public void Remove(string key) { if (Contains(key))//检测存在时中会自动清除cacheState { try { theCache.Remove(key); cacheState.Remove(key); } catch { errorCount++; } } } /// /// 清除所有缓存 /// public void Clear() { try { foreach (KeyValuePair item in cacheState) { theCache.Remove(item.Key); } cacheState.Clear(); } catch { errorCount++; } } /// /// 用户手动设置缓存对象已更改 /// /// /// public void SetChange(string key, bool change) { if (cacheState.ContainsKey(key) && Contains(key)) { CacheDependencyInfo info = cacheState[key]; if (info != null) { info.UserSetChange(change); } } else { Add("Ant.ORM.Cache:Temp_" + key, change, null, 0.1);//缓存失效时,产生6秒的key缓冲 } } /// /// 获取缓存对象是否已被用户手动设置更改 /// /// /// public bool GetHasChanged(string key) { if (cacheState.ContainsKey(key) && Contains(key)) { CacheDependencyInfo info = cacheState[key]; if (info != null) { return info.IsChanged ? false : info.UserChange; } } else if (Contains("Ant.ORM.Cache:Temp_" + key)) { return (bool)theCache.Get("Ant.ORM.Cache:Temp_" + key); } return false; } } /// /// 缓存依赖信息 /// public class CacheDependencyInfo { public int CallCount = 0; /// /// 缓存产生的时间 /// public DateTime CreaeTime; /// /// 缓存多少分钟 /// public Double CacheMinutes = 0; DateTime CacheChangeTime = DateTime.MinValue; CacheDependency FileDependency = null; public CacheDependencyInfo(CacheDependency dependency, double cacheMinutes) { if (dependency != null) { FileDependency = dependency; CacheChangeTime = FileDependency.UtcLastModified; } CreaeTime = DateTime.Now; CacheMinutes = cacheMinutes; } /// /// 系统文件依赖是否发生改变 /// public bool IsChanged { get { if (FileDependency != null && (FileDependency.HasChanged || CacheChangeTime != FileDependency.UtcLastModified)) { CacheChangeTime = FileDependency.UtcLastModified; return true; } return false; } } internal bool UserChange = false; public void UserSetChange(bool change) { UserChange = IsChanged ? false : change; } } }