Подтвердить что ты не робот

Всегда ли исполняются финализаторы .net?

Являются ли финализаторы гарантированно выполняемыми в .NET в какой-то момент (резервные отключения питания и т.п.)? Я знаю, как работает GC и что он недетерминирован, когда именно они будут работать.

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

4b9b3361

Ответ 1

Финализаторы могут фактически никогда не выполняться, поскольку поясняет Раймонд Чен. Как ни странно, этот вопрос задают во время его ежегодной недели CLR, всего через два дня после того, как он объяснил это:)

Для ленивых (или, вернее, один) вывод:

Правильно написанная программа не может предположить, что финализаторы будут когда-либо выполняться.

Если вам интересно, можете ли вы полагаться на финализаторы, это уже все, что вам нужно знать: не полагайтесь на финализаторы.

Как сказал Раймонд Чен в связанной статье:

Финализаторы являются защитной сетью, а не основным средством для рекультивации ресурсов.

Если вы ищете, как выпустить ресурсы, посмотрите на шаблон одноразового использования.


Финализатор может не запускаться, например, если:

  • Другой финализатор генерирует исключение.
  • Еще один финализатор занимает более 2 секунд.
  • Все финализаторы вместе занимают более 40 секунд.
  • AppDomain сбой или разгрузка (хотя вы можете обойти это с помощью критического финализатора (CriticalFinalizerObject, SafeHandle или что-то в этом роде)
  • Сбор мусора не происходит
  • Сбой процесса

(Примечание: значения времени могут меняться со временем, но, конечно же, это было верно некоторое время назад.

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

Ответ 2

Если финализатор генерирует исключение, другие финализаторы не будут выполняться.

Вы также можете подавить финализаторы, если вы вызываете SuppressFinalizer на объект.

От MSDN (Object.Finalize):

Метод Finalize может не работать до завершения или вообще не запускаться при следующих исключительных обстоятельствах:

  • Другой финализатор блокирует бесконечно (переходит в бесконечный цикл, пытается получить блокировку, которую он никогда не сможет получить и т.д.). Поскольку среда выполнения пытается запустить финализаторы до завершения, другие финализаторы могут не вызываться, если финализатор блокирует бесконечно.
  • Процесс завершается без возможности выполнения очистки. В этом случае первое уведомление о завершении процесса представляет собой уведомление DLL_PROCESS_DETACH.