Когда вы не можете использовать SafeHandle вместо финализатора / IDisposable?

#c# #dispose #idisposable #finalizer

#c# #утилизировать #idisposable #финализатор

Вопрос:

Когда вы смотрите на проблему с финализатором / IDisposable в целом, обычно видно, что в конце, после всего длинного описания, будет что-то вроде «LOL, то, что я сказал, на самом деле бесполезно, вы должны использовать SafeHandle вместо пока!» Итак, мне интересно, в каком случае SafeHandle не подходит, так что вам приходится прибегать к старому способу финализации / IDisposable?

Ответ №1:

Очевидно, что когда неуправляемый ресурс, который вы переносите, не приобретается через дескриптор. Что редко, но не неслыханно. Примером может быть написание оболочек в коде C / CLI, обычно выполняемое для обертывания собственного класса C . Тогда ресурсом является память. Неуправляемый вид.

Тем не менее, вы можете потратить карьеру на написание управляемого кода и никогда не написать финализатор. Финализаторы принадлежат классам framework.

Ответ №2:

Когда вы не можете использовать SafeHandle вместо финализатора / IDisposable?

Очевидный ответ — почти никогда, безопасные дескрипторы предлагают много преимуществ.

Но код внутри ReleasHandle() должен соответствовать ограничениям ограниченной области выполнения (CER) . Он может (должен) не вызывать код, который может вызвать сбой или блокировку. Итак, если ваша очистка более сложная и «ненадежная», вам все равно придется использовать финализатор / деструктор.

Но для дескрипторов (OS) вы можете и должны всегда использовать SafeHandle.

Ответ №3:

Многие типы неуправляемых ресурсов могут выполнять свои обязанности по очистке с помощью простого вызова API для дескриптора. Такие ресурсы могут (и часто должны) быть удобно инкапсулированы в SafeHandle. Некоторые другие типы неуправляемых ресурсов (например, подписки на события, принадлежащие издателям-долгожителям) имеют обязанности по очистке, которые не очень хорошо могут быть обработаны с помощью финализатора. Финализаторы могут быть бесполезны, если семантически бесполезные сильные ссылки сохраняют заброшенные объекты живыми, и могут быть непригодны для ресурсов, которые должны быть очищены потоком, который их создает. Нет необходимости писать пользовательский финализатор для таких ресурсов, потому что ни один тип финализатора не устраняет абсолютную 100% необходимость обеспечения детерминированного удаления.

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