138 lines
4.8 KiB
C#
138 lines
4.8 KiB
C#
//using System.Collections.Concurrent;
|
|
|
|
//namespace Kit.Helpers
|
|
//{
|
|
// /// <summary>Сервис для синхронизации потоков по ключу на основе словаря в памяти приложения</summary>
|
|
// /// <typeparam name="TKey">ключ синхронизации</typeparam>
|
|
// public sealed class MemoryLockDictionaryService : ILockDictionaryService
|
|
// {
|
|
// private readonly ConcurrentDictionary<string, LockValue> _lockObjects = new ConcurrentDictionary<string, LockValue>();
|
|
// private readonly TimeSpan _cleanupInterval = TimeSpan.FromSeconds(45);
|
|
// private readonly TimeSpan _expirationTime = TimeSpan.FromSeconds(10);
|
|
// private const int _refreshIntervalMs = 100;
|
|
|
|
// private struct LockValue
|
|
// {
|
|
// public object LockObject { get; }
|
|
// public DateTime DateStart { get; private set; }
|
|
// public LockValue()
|
|
// {
|
|
// LockObject = new object();
|
|
// DateStart = DateTime.UtcNow;
|
|
// }
|
|
|
|
// public void UpdateDate() => DateStart = DateTime.UtcNow;
|
|
// }
|
|
|
|
// public MemoryLockDictionaryService()
|
|
// {
|
|
// StartCleanupTask();
|
|
// }
|
|
|
|
// private string GetTypeMask(string type) => $"$t${(type ?? "no_type")}$t$";
|
|
// private string GetKeyMask(string key) => $"$k${(key ?? "no_key")}$k$";
|
|
// private string GetLockKey(string type, string key) => $"{GetTypeMask(type)}_{GetKeyMask(key)}";
|
|
|
|
// public int GetLockCount(string type)
|
|
// {
|
|
// return _lockObjects.Count(x => x.Key.StartsWith(GetTypeMask(type)));
|
|
// }
|
|
|
|
// public int GetLockCount(string type, string key)
|
|
// {
|
|
// return _lockObjects.Count(x => x.Key.Equals(GetLockKey(type, key)));
|
|
// }
|
|
|
|
// public void ExecuteOnLock(string type, string key, Action action)
|
|
// {
|
|
// if (type == null)
|
|
// {
|
|
// throw new ArgumentNullException(nameof(type));
|
|
// }
|
|
// if (key == null)
|
|
// {
|
|
// throw new ArgumentNullException(nameof(key));
|
|
// }
|
|
// if (action == null)
|
|
// {
|
|
// throw new ArgumentNullException(nameof(action));
|
|
// }
|
|
|
|
// string lockKey = GetLockKey(type, key);
|
|
|
|
// var lockObject = GetOrCreateLockObject(key);
|
|
// lock (lockObject)
|
|
// {
|
|
// // Периодически обновляя дату начала блокировки, выполняем операцию
|
|
// using (var timer = new Timer(_ => UpdateLastAccess(key), null, 0, _refreshIntervalMs))
|
|
// {
|
|
// action();
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// public TResult ExecuteOnLock<TResult>(string type, string key, Func<TResult> action)
|
|
// {
|
|
// if (type == null)
|
|
// {
|
|
// throw new ArgumentNullException(nameof(type));
|
|
// }
|
|
// if (key == null)
|
|
// {
|
|
// throw new ArgumentNullException(nameof(key));
|
|
// }
|
|
// if (action == null)
|
|
// {
|
|
// throw new ArgumentNullException(nameof(action));
|
|
// }
|
|
|
|
// string lockKey = GetLockKey(type, key);
|
|
|
|
// var lockObject = GetOrCreateLockObject(key);
|
|
// lock (lockObject)
|
|
// {
|
|
// // Периодически обновляя дату начала блокировки, выполняем операцию
|
|
// using (var timer = new Timer(_ => UpdateLastAccess(key), null, 0, _refreshIntervalMs))
|
|
// {
|
|
// return action();
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// private object GetOrCreateLockObject(string key)
|
|
// {
|
|
// return _lockObjects.GetOrAdd(key, _ => new LockValue()).LockObject;
|
|
// }
|
|
|
|
// private void UpdateLastAccess(string key)
|
|
// {
|
|
// if (_lockObjects.TryGetValue(key, out var value))
|
|
// _lockObjects[key].UpdateDate();
|
|
// }
|
|
|
|
// private void StartCleanupTask()
|
|
// {
|
|
// Task.Run(async () =>
|
|
// {
|
|
// while (true)
|
|
// {
|
|
// await Task.Delay(_cleanupInterval);
|
|
// CleanupExpiredLocks();
|
|
// }
|
|
// });
|
|
// }
|
|
|
|
// private void CleanupExpiredLocks()
|
|
// {
|
|
// var now = DateTime.UtcNow;
|
|
// foreach (var key in _lockObjects.Keys)
|
|
// {
|
|
// if (_lockObjects.TryGetValue(key, out var value) && now - value.DateStart > _expirationTime)
|
|
// {
|
|
// _lockObjects.TryRemove(key, out _);
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//}
|