using Microsoft.Extensions.Caching.Memory; namespace YLErp.Helpers { /// /// 多线程并发锁帮助类 /// public static class LockHelper { /// /// 获取用于现成锁定的对象,解决前端的并发请求问题 /// /// 唯一标识ID,建议格式为:功能ID+数据ID /// 对象锁定时间,仅在第一次锁定时使用,锁定时间过期后对象被释放 public static object Acquire(string keyId, int lockSeconds = 60) { if (string.IsNullOrEmpty(keyId)) { throw new ArgumentException($"“{nameof(keyId)}”不能是 Null 或为空", nameof(keyId)); } lock (InnerHelper.MemoryCache) { var obj = InnerHelper.MemoryCache.Get(keyId); if (obj == null) { var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(lockSeconds)); InnerHelper.MemoryCache.Set(keyId, obj = new object(), cacheEntryOptions); } return obj; } } /// /// 获取用于现成锁定的对象,解决前端的并发请求问题 /// /// 唯一标识ID,建议格式为:功能ID+数据ID /// 锁定实例处理器 /// 对象锁定时间,仅在第一次锁定时使用,锁定时间过期后对象被释放 public static T Acquire(string keyId, ILockInstanceHandler instanceHandler, int lockSeconds = 60) where T : class { if (string.IsNullOrEmpty(keyId)) { throw new ArgumentException($"“{nameof(keyId)}”不能是 Null 或为空", nameof(keyId)); } if (instanceHandler is null) { throw new ArgumentNullException(nameof(instanceHandler)); } lock (InnerHelper.MemoryCache) { var obj = InnerHelper.MemoryCache.Get(keyId); if (obj == null) { var cacheEntryOptions = new MemoryCacheEntryOptions().SetSlidingExpiration(TimeSpan.FromSeconds(lockSeconds)); InnerHelper.MemoryCache.Set(keyId, obj = instanceHandler.Create(), cacheEntryOptions); } else { instanceHandler.Update((T)obj); } return (T)obj; } } public static void Release(string keyId) { if (string.IsNullOrEmpty(keyId)) { return; } lock (InnerHelper.MemoryCache) { InnerHelper.MemoryCache.Remove(keyId); } } } /// /// 锁定实例处理 /// public interface ILockInstanceHandler where T : class { /// /// 创建新的锁定实例(如果缓存中不存在的话) /// T Create(); /// /// 更新锁定实例(如果缓存中存在的话) /// void Update(T instance); } }