Заблокировать объектный словарь, который освобождает ненужные элементы?

#c# #asp.net #.net #caching #garbage-collection

#c# #asp.net #.net #кэширование #сбор мусора

Вопрос:

Мне нужно синхронизировать критический раздел, но только если код работает с теми же данными (определяется идентификаторами объектов). Вот почему я реализовал контейнер объектов блокировки, который динамически создает объекты блокировки на основе идентификатора строки. Объекты блокировки хранятся в словаре и используются повторно, если кто-то запрашивает объект с тем же ключом.

Проблема в том, что миллионы комбинаций ключа блокировки и объектов блокировки в настоящее время остаются в словаре и потребляют память навсегда.

Как создать такой словарь, чтобы он удалял ненужные объекты блокировки и, таким образом, освобождал память?

Мои идеи:

  1. Храните объекты блокировки как слабые ссылки и просматривайте словарь один раз и удаляйте ключи, где значение!IsAlive
  2. Храните объекты блокировки как слабые ссылки, но на этот раз реализуйте финализатор в классе LockObject и удалите ключ из словаря при его срабатывании

Есть ли у меня другие варианты?

Комментарии:

1. Небольшое объяснение вашей реальной проблемы, которую вы хотите решить, было бы неплохо.

2. Критический раздел, о котором я говорю, вычисляет, выполняет ли пользователь определенное условие или нет. Условие задается администратором веб-сайта (может быть очень сложным). Оценка состояния может запускаться различными событиями и должна быть синхронизирована, но только для отдельной комбинации идентификаторов пользователя и ConditionID. Помогло ли это?

3. Я System.Runtime.Caching.MemoryCache много использовал в подобных случаях

4. Ну, насколько я знаю, MemoryCache может освободить элемент, даже если есть ссылка на него где-то еще. Это дисквалифицирует его, потому что я не хочу, чтобы объект освобождался, когда какой-то поток использует его для блокировки. Или я что-то пропустил?

Ответ №1:

Я знаю, что вопрос очень старый, но на случай, если кто-то наткнется на это и столкнется с той же проблемой, взгляните на AsyncKeyedLock, который решает проблему. Вы можете использовать:

 using (await _locker.LockAsync(myObject.Id))
{
   ...
}