Когда возвращать объект обратно в его пул
Я хочу использовать объектный пул в моем приложении C#, и я знаю, что в C# нет подсчета ссылок. Если один и тот же объект может быть передан нескольким потокам, как я могу узнать, когда больше нет ссылок на объект, чтобы я мог вернуть его в пул объектов?
Я думал сделать это в dispose
метод, но это слишком поздно, и его нельзя вернуть в пул, поскольку он удаляется.
3 ответа
Реализация объектного пула в.Net может быть выполнена с помощью Finalizer.
На самом деле, большинство пулов, реализованных в.Net, также делают это (например, пул соединений с БД).
Использование финализатора позволяет вам узнать, что на объект больше не ссылаются, так как финализатор вызывается после того, как GC определит, что нет возможных маршрутов к объекту.
Техника не в том, чтобы делать какие-либо разрушительные методы в вашем Dispose (я получу это дальше) и завершить метод.
Допустим, у вас есть тип PooledObject и тип ObjectPool, который управляет пулом.
В ObjectPool добавьте внутренние методы с именем ReturnToPool(PooledObject obj), которые получат объект и сделают его доступным для других вызывающих.
В тип PooledObject вы должны добавить внутренний метод с именем ReleaseResources - который будет вызываться ObjectPool только тогда, когда весь пул должен быть удален из памяти - в этом методе вы реализуете логику удаления (закрывающие дескрипторы, освобождая неуправляемую память)., так далее..). В методах PooledObject Dispose и Finalize вы должны вызывать методы ReturnToPool в ObjectPool (статические или внутренне хранящиеся в объединенном объекте) - это называется - воскресение. При вызове метода ReturnToPool в финализаторе вы фактически воскрешаете объект и снова делаете его доступным.
Убедитесь, что вы перерегистрируете PooledObject для финализации в методе ReturnToPool в методе ObjectPool - GC.ReRegisterForFinalize.
Конечно, оба этих типа должны быть в одной сборке. (чтобы они могли вызывать внутренние методы друг друга)
Однако вы должны реализовать шаблон Dispose в любом случае. Это сэкономит время, когда объект больше не используется (например, после выхода из области применения) и вернет объект в пул.
Надеюсь это поможет. Офир.
как я могу узнать, когда больше нет ссылок на объект, чтобы я мог вернуть его в пул объектов.
Гектометр Вы осуществляете подсчет ссылок.
Что также работает, так это прокси-сервер, который имеет метод Disposable. После завершения работы с прокси реализация dispose помещает внутренний объект в пул (внешний объект очень маленький).
Но в конце вы должны знать, когда выпустить. Это называется программированием. Это имеет смысл только для "толстых" объектов со значительными издержками инициализации, и тогда вам действительно нужно убедиться, что вы точно знаете, когда вернуть их обратно с помощью логики (т. Е. Пользовательского счета и т. Д.).
Должно быть в Close
/ Release
метод. Ответственность за создание и удаление экземпляра лежит на самом ObjectPool.
Чтобы запросить / освободить объект из / в ObjectPool, используйте Open
/ Close
или же Acquire
/ Release
,
В статье Code Project, C# Object Pooling, представлена хорошая легкая реализация пользовательского пула объектов.
Вы также можете взглянуть на механизм пула соединений ADO.NET, чтобы получить подсказку о примере пула объектов.