1. 程式人生 > 其它 >C# 記憶體快取工具類 MemoryCacheUtil

C# 記憶體快取工具類 MemoryCacheUtil

C# 記憶體快取工具類 MemoryCacheUtil

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Timers;

namespace Utils
{
    /// <summary>
    /// 快取
    /// 快取資料儲存在記憶體中
    
/// 適用於CS專案,BS專案慎用 /// </summary> public static class MemoryCacheUtil { #region 變數 /// <summary> /// 記憶體快取 /// </summary> private static ConcurrentDictionary<string, CacheData> _cacheDict = new ConcurrentDictionary<string, CacheData>();
/// <summary> /// 對不同的鍵提供不同的鎖,用於讀快取 /// </summary> private static ConcurrentDictionary<string, string> _dictLocksForReadCache = new ConcurrentDictionary<string, string>(); /// <summary> /// 過期快取檢測Timer /// </summary> private static
Timer _timerCheckCache; #endregion #region 靜態建構函式 static MemoryCacheUtil() { _timerCheckCache = new Timer(); _timerCheckCache.Interval = 60 * 1000; _timerCheckCache.Elapsed += _timerCheckCache_Elapsed; _timerCheckCache.Start(); } #endregion #region 獲取並快取資料 /// <summary> /// 獲取並快取資料 /// 高併發的情況建議使用此過載函式,防止重複寫入記憶體快取 /// </summary> /// <param name="cacheKey"></param> /// <param name="func">在此方法中初始化資料</param> /// <param name="expirationSeconds">快取過期時間(秒),0表示永不過期</param> /// <param name="refreshCache">立即重新整理快取</param> public static T TryGetValue<T>(string cacheKey, Func<T> func, int expirationSeconds = 0, 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); return value; } } } #endregion #region SetValue 儲存鍵值對 /// <summary> /// 儲存鍵值對 /// </summary> /// <param name="key">快取鍵</param> /// <param name="value"></param> /// <param name="expirationSeconds">過期時間(秒),0表示永不過期</param> internal static void SetValue(string key, object value, int expirationSeconds = 0) { try { CacheData data = new 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寫快取錯誤"); } } #endregion #region GetValue 獲取鍵值對 /// <summary> /// 獲取鍵值對 /// </summary> internal static object GetValue(string key) { try { CacheData data; if (_cacheDict.TryGetValue(key, out data)) { if (data.expirationSeconds > 0 && DateTime.Now.Subtract(data.updateTime).TotalSeconds > data.expirationSeconds) { CacheData temp; _cacheDict.TryRemove(key, out temp); return null; } return data.value; } return null; } catch (Exception ex) { LogUtil.Error(ex, "MemoryCacheUtil讀快取錯誤"); return null; } } #endregion #region Delete 刪除快取 /// <summary> /// 刪除快取 /// </summary> internal static void Delete(string key) { CacheData temp; _cacheDict.TryRemove(key, out temp); } #endregion #region DeleteAll 刪除全部快取 /// <summary> /// 刪除全部快取 /// </summary> internal static void DeleteAll() { _cacheDict.Clear(); } #endregion #region 過期快取檢測 /// <summary> /// 過期快取檢測 /// </summary> private static void _timerCheckCache_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { Task.Run(() => { try { foreach (string cacheKey in _cacheDict.Keys.ToList()) { CacheData data; if (_cacheDict.TryGetValue(cacheKey, out data)) { if (data.expirationSeconds > 0 && DateTime.Now.Subtract(data.updateTime).TotalSeconds > data.expirationSeconds) { CacheData temp; string strTemp; _cacheDict.TryRemove(cacheKey, out temp); _dictLocksForReadCache.TryRemove(cacheKey, out strTemp); } } } } catch (Exception ex) { LogUtil.Error(ex, "過期快取檢測出錯"); } }); } #endregion } }
View Code

CacheData類:

/// <summary>
/// 快取資料
/// </summary>
[Serializable]
public class CacheData
{
    /// <summary>
    ////// </summary>
    public string key { get; set; }
    /// <summary>
    ////// </summary>
    public object value { get; set; }
    /// <summary>
    /// 快取更新時間
    /// </summary>
    public DateTime updateTime { get; set; }
    /// <summary>
    /// 過期時間(秒),0表示永不過期
    /// </summary>
    public int expirationSeconds { get; set; }

    /// <summary>
    /// 快取資料
    /// </summary>
    /// <param name="key">快取鍵</param>
    /// <param name="value"></param>
    public CacheData(string key, object value)
    {
        this.key = key;
        this.value = value;
    }
}
View Code

如何使用:

private void button2_Click(object sender, EventArgs e)
{
    List<string> list = MemoryCacheUtil.TryGetValue<List<string>>("cacheKey001", () =>
    {
        return QueryData();
    });
}

/// <summary>
/// 模擬從資料庫查詢資料
/// </summary>
private List<string> QueryData()
{
    List<string> result = new List<string>();

    for (int i = 0; i < 10; i++)
    {
        result.Add(i.ToString());
    }

    return result;
}
View Code