Финализаторы .NET всегда выполняются?

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

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

18
задан mafu 11 August 2010 в 12:26
поделиться

2 ответа

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

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

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

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

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

Финализаторы - это подстраховка, а не основное средство для освоения ресурсов.

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


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

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

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

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

24
ответ дан 30 November 2019 в 08:03
поделиться

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

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

Из MSDN (Object.Finalize):

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

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

Похожие вопросы: