80 lines
2.8 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|