102 lines
3.4 KiB
C#
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);
|
|
}
|
|
}
|