Kit.Core/LibCommon/Kit.Core.Helpers/Service/LockService.cs

80 lines
2.8 KiB
C#

namespace Kit.Helpers
{
public interface ILockService<TKey>
{
TResult Lock<TResult>(TKey lockKey, Func<TResult> action);
void Lock(TKey lockKey, Action action);
}
public class LockService<TKey> : ILockService<TKey>
{
private object _lockObjectLock = new object();
private IDictionary<TKey, object> _lockObjects = new Dictionary<TKey, object>();
/// <summary> Блокировка операции по ключу </summary>
/// <param name="lockKey"> Ключ для блокировки </param>
/// <param name="action"> Выполняемая операция </param>
public TResult Lock<TResult>(TKey lockKey, Func<TResult> action)
{
try
{
lock (GetLockObject(lockKey))
{
return action();
}
}
finally
{
RemoveLockObject(lockKey);
}
}
/// <summary> Блокировка операции по ключу </summary>
/// <param name="lockKey"> Ключ для блокировки </param>
/// <param name="action"> Выполняемая операция </param>
public void Lock(TKey lockKey, Action action)
{
try
{
lock (GetLockObject(lockKey))
{
action();
}
}
finally
{
RemoveLockObject(lockKey);
}
}
/// <summary> Получение объекта для блокировки по ключу </summary>
/// <param name="lockKey"> Ключ для блокировки </param>
/// <returns> Объект блокировки, соответствующий ключу </returns>
private object GetLockObject(TKey lockKey)
{
lock (_lockObjectLock)
{
if (_lockObjects.ContainsKey(lockKey) == false)
{
_lockObjects.Add(lockKey, new object());
}
return _lockObjects[lockKey];
}
}
/// <summary> Удаление объекта блокировки, соответствующего ключу </summary>
/// <param name="lockKey"> Ключ для блокировки </param>
private void RemoveLockObject(TKey lockKey)
{
/// дожидаемся освобождения объекта
lock (this.GetLockObject(lockKey)) { }
/// удаляем объект блокировки из очереди
lock (_lockObjectLock)
{
_lockObjects.Remove(lockKey);
}
}
}
}