用C#封装一个线程安全的缓存器,达到目标定时更新
错峰缓存,减少数据库IO瓶颈。
using System.Collections.Concurrent; using Tools; namespace SpacePhoneAPI.BackTask { public class CacheManager<T> { private static CacheManager<T>? _instance; private static readonly object LockObject = new object(); private BlockingCollection<T> buffer; private int MaxCache = 100; public delegate Task MyEventHandler(List<T> list); public event MyEventHandler? UpdateDataEvent; public CacheManager(int maxCache) { MaxCache = maxCache; buffer = new BlockingCollection<T>(MaxCache); } public static CacheManager<T> GetInstance(int maxCache) { if (_instance == null) { lock (LockObject) { if (_instance == null) { _instance = new CacheManager<T>(maxCache); } } } return _instance; } public int GetCount() { return buffer.Count; } /// <summary> /// 添加数据,触发被动更新 /// </summary> /// <returns></returns> public void AddData(T data) { buffer.Add(data); NLogHelper.Debug("debug:" + buffer.Count.ToString()); if (buffer.Count >= MaxCache) { UpdateDataEvent?.Invoke(buffer.ToList()); buffer.Clear(); } } /// <summary> /// 主动更新 /// </summary> /// <returns></returns> public async Task InitiativeUpdate() { await Task.Run(() => { if (buffer.Count > 0) { UpdateDataEvent?.Invoke(buffer.ToList()); buffer.Clear(); } }); } } }
扩展方法
public static class ExtendBlockingCollection { public static void Clear<T>(this BlockingCollection<T> blockingCollection) { if (blockingCollection == null) { throw new ArgumentNullException("blockingCollection"); } while (blockingCollection.Count > 0) { T item; blockingCollection.TryTake(out item); } } }
试用测试:
var cache = CacheManager<int>.GetInstance(10); cache.UpdateDataEvent += Cache_UpdateDataEvent; for (int i = 0; i < 100; i++) { cache.AddData(i); Console.WriteLine($"Add:" + i); } Console.ReadKey(); async Task Cache_UpdateDataEvent(List<int> list) { await Task.Delay(TimeSpan.FromSeconds(1)); string tt = ""; foreach (var item in list) tt += item + ","; Console.WriteLine($"Inserted into database:" + tt); }
文章评论