2013-12-16 2 views
0

Мне нужно создать потокобезопасный кеш одноразовых объектов. Как я это вижу:Создать потокобезопасный кеш одноразовых объектов

  1. У меня есть класс данных, что я хочу, чтобы кэшировать, бывший MyData
  2. Я создаю некоторые коллекции (ConcurrentDictionary, например) для MyData
  3. У меня есть метод, который создает новый экземпляр MyData, используя некоторый ключ.
  4. Когда мне нужно получить MyData для некоторого ключа, я проверяю, существует ли он в моем хранилище, а затем используйте его из коллекции, иначе он создает новый экземпляр и помещает его в коллекцию.
  5. У меня есть событие, когда я должен аннулировать кеш. На этом событии я очищаю хранилище.

Недостатки в том, что MyData является одноразовым. Я не знаю, когда следует вызвать метод Dispose. Я не могу вызвать метод Dispose при очистке коллекции от события clear-cache, потому что какой-то поток может мгновенно использовать эти экземпляры MyData.

Какой шаблон выбрать?

+0

Если ваши объекты разделены между многими потребителями, то не имеет значения, кто именно вызывает Dispose; все потребители * должны * сотрудничать, чтобы все было без проблем.Возможно, вы должны быть готовы поймать 'ObjectDisposedException'. – Jon

+0

Являются ли объекты одного типа? –

+0

@ LasseV.Karlsen, какое отличие делает тот же тип, что все они IDissposable? – Liran

ответ

2

Я не вижу большого смысла при одновременном сборе в случае, если потребители кэш должен иметь возможность завершить текущую операцию с элементом из кеша. действительно нужна синхронизация здесь.

Наиболее очевидно, что вы можете сделать здесь, это использовать ReaderWriteLockSlim и обертку вокруг обычного Dictionary<TKey, TValue>.

Когда кто-то хочет использовать элемент из кеша, он получает доступ для чтения. Когда кто-то хочет изменить кеш (вообще добавить элемент или вообще недействить кеш), он получает доступ на запись (следовательно, автор не может аннулировать кеш, пока последний читатель не освободит блокировку).

Другой вариант - рассмотреть подход, когда вы просто ловите ObjectDisposedException. Но этот подход предполагает, что работа с currect может быть прервана извне.

+0

Какое отношение это имеет к распоряжению? –

1

Я думаю, вы должны инкапсулировать механизм кэширования, и никто не должен вызывать объект, который обертывает словарь, должен делать это без побочного вмешательства (шаблон Singleton был бы хорош здесь, и весь доступ к словарю должен быть заблокирован, в случае, если вы сделали недействительным кеш, просто заблокируйте его, удалите его и очистите. Если вам нужна помощь с синглтоном, скажите мне.

+0

Thx для ответа! Основная проблема, что в моем нынешнем классе кеша не может сказать, что кто-нибудь использует этот экземпляр MyData или нет. Так что я не могу распоряжаться им. Теперь я думаю, что создам некоторый метод для потоков, чтобы они могли уведомлять класс кеша, когда они начинают и заканчивают использование MyData. Таким образом, на событии я очищу сбор, удалю все экземпляры, которые не используются, а затем освободят занятые элементы, когда они освободятся. – Yavanosta

+0

вот почему синглтон и блокировка, но забывают блокировку, используйте подход, который @dennis предложил с помощью ReaderWriteLockSlim, кажется, нет. – Liran

1

Если объекты являются логически неизменными, несколько дорогими для создания и, как известно, не потребляют неисправимых ресурсов и лишь небольшое количество взаимозаменяемых; и если отслеживание всех ссылок на них будет непрактичным, вы можете использовать кеш коротких слабых ссылок. Такая ситуация была бы одним из немногих раз, когда я мог бы считать разумным «полагаться» на завершение, поскольку только один объект, соответствующий данному ключу, когда-либо существовал бы за пределами «freachable» очереди (список объектов, нуждающихся в очистке) в любой момент времени , Одним из преимуществ этого подхода является то, что при условии, что вы избежите воскрешения объектов, которые стали пригодными для завершения, вашему коду не нужно слишком беспокоиться о проблемах с потоками в большинстве случаев. Вам придется периодически чистить записи, связанные с ними слабые ссылки, и следить за тем, что запись в кэш может быть обновлена ​​новым объектом после того, как он будет признан мертвым, но GC должен обеспечить, чтобы объекты не очищайтесь, пока кто-то их использует.

Смежные вопросы