Итак, на чем мы остановились? На данный момент мы уже рассмотрели детерминированное завершение, которое работает так:
- GC отслеживает, на какие объекты ссылаются;
- у GC всегда есть низкоприоритетный поток, сканирующий его объекты, чтобы определить, ссылаются ли еще на объект;
- второй низкоприоритетный поток отвечает за очистку; этот поток вызывает метод Finalize объекта.
Этот подход действительно помогает решить проблему циклических ссылок, но влечет за собой другие проблемы. Например, нет гарантии, что метод Finalize будет вызван когда-нибудь в течение периода выполнения! А это именно то, что в детерминированном завершении понимается под словом детерминированное. Короче, вопрос ставится так: как выполнить очистку и убедиться, что отвечающий за очистку код вызывается каждый раз?
В случае освобождения дефицитных ресурсов Microsoft предлагает решение, в основе которого лежит метод Dispose. Эта схема рекомендует, чтобы у объекта был открытый метод с универсальным именем, например Cleanup или Dispose, который пользователь согласно инструкции должен вызывать, закончив применять объект. При этом всю очистку в этом методе определяет разработчик класса. Фактически вы увидите, что для этой цели у многих классов из библиотеки .NET Framework реализован метод Dispose. В качестве примера приведу выдержку из документации класса System. Wmforms. Traylcon: “при завершении использования Tray Icon вызовите метод Dispose”.