C# 内存缓存工具类 MemoryCacheUtil
using System; System.Collections.Concurrent; System.Collections.Generic; System.linq; System.Security.Cryptography; System.Text; System.Threading.Tasks; System.Timers;namespace Utils{ /// <summary> /// 缓存 缓存数据存储在内存中 适用于CS项目,BS项目慎用 </summary> public static class MemoryCacheUtil { #region 变量 <summary> 内存缓存 </summary> private static ConcurrentDictionary<string,CacheData> _cacheDict = new ConcurrentDictionary<(); 对不同的键提供不同的锁,用于读缓存 string> _dictLocksForReadCache = string> 过期缓存检测Timer static Timer _timerCheckCache; #endregion #region 静态构造函数 MemoryCacheUtil() { _timerCheckCache = new Timer(); _timerCheckCache.Interval = 60 * 1000; _timerCheckCache.Elapsed += _timerCheckCache_Elapsed; _timerCheckCache.Start(); } #region 获取并缓存数据 获取并缓存数据 高并发的情况建议使用此重载函数,防止重复写入内存缓存 </summary> <param name="cacheKey">键</param> <param name="func">在此方法中初始化数据<param name="expirationSeconds">缓存过期时间(秒),0表示永不过期<param name="refreshCache">立即刷新缓存</param> static T TryGetValue<T>(string cacheKey,Func<T> func,1)">int expirationSeconds = 0,1)">bool refreshCache = false) { lock (_dictLocksForReadCache.GetorAdd(cacheKey,cacheKey)) { object cacheValue = MemoryCacheUtil.GetValue(cacheKey); if (cacheValue != null && !refreshCache) { return (T)cacheValue; } else { T value = func(); MemoryCacheUtil.SetValue(cacheKey,value,expirationSeconds); value; } } } #region SetValue 保存键值对 保存键值对 <param name="key">缓存键<param name="value">值过期时间(秒),0表示永不过期internal voID SetValue(string key,1)">object value,1)">0try { CacheData data = CacheData(key,value); data.updateTime = DateTime.Now; data.expirationSeconds = expirationSeconds; CacheData temp; _cacheDict.TryRemove(key,out temp); _cacheDict.TryAdd(key,data); } catch (Exception ex) { LogUtil.Error(ex,"MemoryCacheUtil写缓存错误"); } } #region GetValue 获取键值对 获取键值对 object GetValue(string key) { { CacheData data; if (_cacheDict.TryGetValue(key,1)"> data)) { if (data.expirationSeconds > 0 && DateTime.Now.Subtract(data.updateTime).TotalSeconds > data.expirationSeconds) { CacheData temp; _cacheDict.TryRemove(key,1)"> temp); return null; } data.value; } ; } MemoryCacheUtil读缓存错误); ; } } #region Delete 删除缓存 删除缓存 voID Delete( key) { CacheData temp; _cacheDict.TryRemove(key,1)"> temp); } #region Deleteall 删除全部缓存 删除全部缓存 voID Deleteall() { _cacheDict.Clear(); } #region 过期缓存检测 过期缓存检测 voID _timerCheckCache_Elapsed(object sender,System.Timers.ElapsedEventArgs e) { Task.Run(() => { { foreach (string cacheKey in _cacheDict.Keys.ToList()) { CacheData data; if (_cacheDict.TryGetValue(cacheKey,1)"> data)) { data.expirationSeconds) { CacheData temp; strTemp; _cacheDict.TryRemove(cacheKey,1)"> temp); _dictLocksForReadCache.TryRemove(cacheKey,1)"> strTemp); } } } } (Exception ex) { LogUtil.Error(ex,1)">过期缓存检测出错); } }); } #endregion }}VIEw Code
为什么BS项目慎用?因为IIS会回收进程,所以需要注意一下。
为什么过期缓存检测遍历代码是foreach (string cacheKey in _cacheDict.Keys.ToList()),要使用ToList()?_cacheDict.Keys不是线程安全的,防止并发异常。
为什么加锁的代码是lock (_dictLocksForReadCache.GetorAdd(cacheKey,cacheKey))?为了支持多线程并发,防止重复进入func函数。
CacheData类:
<summary> 缓存数据</summary>[Serializable] CacheData{ 键 string key { get; set; } 值 object value { 缓存更新时间 public DateTime updateTime { 过期时间(秒),0表示永不过期 int expirationSeconds { ; } 缓存数据 </summary> </param> </param> public CacheData( value) { this.key = key; this.value = value; }}VIEw Code
如何使用:
voID button2_Click(string> List = MemoryCacheUtil.TryGetValue<List<string>>(cacheKey001",() => { queryData(); });} 模拟从数据库查询数据private List< queryData(){ List<string> result = new List<(); for (int i = 0; i < 10; i++) { result.Add(i.ToString()); } result;}VIEw Code
多线程并发测试:
TestMemoryCache(){ Log(开始); 5; i++) { Task.Run(() => { string str1 = MemoryCacheUtil.TryGetValue<string>(1 { Thread.Sleep(2000); Log(取数据1return ; }); Log(str1); }); Task.Run(() =>string str2 = MemoryCacheUtil.TryGetValue<2取数据2; }); Log(str2); }); Task.Run(() =>string str3 = MemoryCacheUtil.TryGetValue<3取数据3; }); Log(str3); }); }}VIEw Code
总结
以上是内存溢出为你收集整理的C# 内存缓存工具类 MemoryCacheUtil全部内容,希望文章能够帮你解决C# 内存缓存工具类 MemoryCacheUtil所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)