Files
zszq-trs/Framework/YLErp.Core/Helpers/LockHelper.cs
T
2024-05-09 14:06:26 +08:00

102 lines
3.4 KiB
C#

using Microsoft.Extensions.Caching.Memory;
namespace YLErp.Helpers
{
/// <summary>
/// 多线程并发锁帮助类
/// </summary>
public static class LockHelper
{
/// <summary>
/// 获取用于现成锁定的对象,解决前端的并发请求问题
/// </summary>
/// <param name="keyId">唯一标识ID,建议格式为:功能ID+数据ID</param>
/// <param name="lockSeconds">对象锁定时间,仅在第一次锁定时使用,锁定时间过期后对象被释放</param>
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;
}
}
/// <summary>
/// 获取用于现成锁定的对象,解决前端的并发请求问题
/// </summary>
/// <param name="keyId">唯一标识ID,建议格式为:功能ID+数据ID</param>
/// <param name="instanceHandler">锁定实例处理器</param>
/// <param name="lockSeconds">对象锁定时间,仅在第一次锁定时使用,锁定时间过期后对象被释放</param>
public static T Acquire<T>(string keyId, ILockInstanceHandler<T> 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);
}
}
}
/// <summary>
/// 锁定实例处理
/// </summary>
public interface ILockInstanceHandler<T> where T : class
{
/// <summary>
/// 创建新的锁定实例(如果缓存中不存在的话)
/// </summary>
T Create();
/// <summary>
/// 更新锁定实例(如果缓存中存在的话)
/// </summary>
void Update(T instance);
}
}