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);
}
}