今天由于工作的原因,需要在WCF在用到缓存,但发现WCF没有现成的缓存类,这可能是我用WCF的时间比较短.所以我自己写了一个缓存类.
写的比较简单,但对于项目于那个功能已经够用了.
自定义的缓存功能由两个类和一个委托组成:
CacheValue:用于存储缓存值
Cache:通过HashSet组织缓存项(HashSet自身具有线程安全性)
CacheTimeOut:超时后触发
CacheTimeOut:
public delegate void CacheTimeOut(CacheValue obj);
CacheValue:
public class CacheValue { public event CacheTimeOut TimeOutHandler; /// <summary> /// 上次调用时间 /// </summary> private DateTime lastTime; private int _expired = 1800; private System.Timers.Timer timer = new System.Timers.Timer(); /// <summary> /// Key /// </summary> public string Key { get; set; } /// <summary> /// 值 /// </summary> private object _value; public object Value { get { lastTime = DateTime.Now; return _value; } set { lastTime = DateTime.Now; _value = value; } } /// <summary> /// 过期时间 /// </summary> public int Expired { get { return _expired; } set { _expired = value; } } public CacheValue() { Init(); } public CacheValue(object val) { this.Value = val; Init(); } public CacheValue(object val, int expired) { this.Value = val; this.Expired = expired; Init(); } /// <summary> /// 初始化 /// </summary> private void Init() { timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); lastTime = DateTime.Now; timer.Start(); timer.Interval = 1000; } void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { if (this.Expired < 0) { return; } DateTime now = DateTime.Now; TimeSpan span = now - lastTime; if (span.Seconds >= Expired) { if (TimeOutHandler != null) { TimeOutHandler(this); } } } }
Cache:
public class Cache { public object objKey = new object(); private HashSet<CacheValue> hashCache = new HashSet<CacheValue>(); public HashSet<CacheValue> Caches { get { return hashCache; } } public CacheValue this[string key] { set { if (string.IsNullOrEmpty(key)) { return; } lock (objKey) { CacheValue val = hashCache.SingleOrDefault(t => t.Key == key); if (val != null) hashCache.Remove(val); val = value; val.Key = key; val.TimeOutHandler += new CacheTimeOut(val_TimeOutHandler); hashCache.Add(val); } } get { if (string.IsNullOrEmpty(key)) { return null; ; } return hashCache.SingleOrDefault(t => t.Key == key); } } void val_TimeOutHandler(CacheValue obj) { hashCache.Remove(obj); } public bool Remove(string key) { CacheValue val = hashCache.SingleOrDefault(t => t.Key == key); if (val != null) { return hashCache.Remove(val); } else { return true; } } public void Clear() { hashCache.Clear(); } }
测试:
Cache cache = new Cache(); private void btn_Click(object sender, EventArgs e) { Thread[] ths = new Thread[10]; for (int i = 0; i < ths.Length; i++) { ths[i] = new Thread(new ParameterizedThreadStart(AddCacheItem)); } foreach (Thread th in ths) { th.Start(); } } private void AddCacheItem(object obj) { for (int i = 0; i < 20; i++) { cache[i.ToString()] = new CacheValue(i, i); } } private void btnRead_Click(object sender, EventArgs e) { Thread th = new Thread(new ParameterizedThreadStart(ReadCache)); th.Start(); } private void ReadCache(object obj) { Random random = new Random(); string key; while (cache.Caches.Count > 0) { key = random.Next(19).ToString(); CacheValue val = cache[key]; if (val != null) { Trace.WriteLine(val.Value); } } }