Если был вызван финализатор объекта, могу ли я быть на 100% уверен, что он впоследствии будет удален из памяти?

У меня есть приложение WPF, которое позволяет пользователю открывать, закрывать и повторно открывать произвольное количество дочерних окон.

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

Я знаю о частых случаях утечки памяти в WPF и пришел к выводу, что профилировщик ошибается. Поэтому я добавил следующий код в проблемный класс:

~ProblematicChildWindow()
{
   using (StreamWriter sw = File.CreateText("d:\\garbagecollection.txt"))
   {
      sw.WriteLine(DateTime.Now.ToShortTimeString() + " garbage collected.");
   }
}

Теперь самое странное:

После открытия и закрытия экземпляра ProblematicChildWindow и принудительной сборки мусора я обнаружил новый файл "garbagecollection.txt" в своей папке D:\, НО

Профилировщик памяти VS2015 сообщает мне, что в памяти все еще есть экземпляр ProblematicChildWindow!

Мой вопрос: учитывая тот факт, что экземпляр явно был собран мусором (потому что был вызван финализатор), могу ли я быть уверен, что занятая память будет освобождена?

В этом случае у профилировщика памяти VS2015, похоже, есть ошибка.

ОБНОВЛЕНИЕ: .NET Memory Profiler сообщает мне, что после закрытия в памяти не осталось ни одного экземпляра. Но VS2015 работает (только что еще раз проверил).


person Golvellius    schedule 05.07.2016    source источник
comment
Что произойдет, если принудительно выполнить сборку мусора дважды? В частности, GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();.   -  person Damien_The_Unbeliever    schedule 05.07.2016
comment
На самом деле, когда вызывается финализатор, вы еще не собирали мусор. В конце концов, если бы это было так, как мог бы быть вызван финализатор вашего объекта? Он будет помечен как подлежащий сбору, если он по-прежнему соответствует требованиям, но финализатор может в конечном итоге воскресить рассматриваемый объект.   -  person willaien    schedule 05.07.2016
comment
Возможно, вы захотите прочитать запись в блоге Эрика Липперта Когда все, что ты знаешь, неверно   -  person juharr    schedule 05.07.2016
comment
@ Damien_The_Unbeliever: я получаю файл с одной строкой, но профилировщик VS сообщает мне, что в памяти все еще есть экземпляр.   -  person Golvellius    schedule 05.07.2016
comment
@juharr: я посмотрю, спасибо.   -  person Golvellius    schedule 05.07.2016


Ответы (3)


Нет, именно поэтому у нас есть такой метод, как GC.WaitForPendingFinalizers:

Когда сборщик мусора находит объекты, которые могут быть утилизированы, он проверяет каждый объект, чтобы определить требования к финализации объекта. Если объект реализует финализатор и не отключил финализацию вызовом SuppressFinalize, объект помещается в список объектов, помеченных как готовые к финализации. Сборщик мусора вызывает методы Finalize для объектов в этом списке и удаляет записи из списка. Этот метод блокируется до тех пор, пока все финализаторы не будут завершены.

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

person Zein Makki    schedule 05.07.2016

Финализатор вызывается сборщиком мусора, когда он распознает объект как неиспользуемый. Однако это не гарантирует, что объект будет собран. Это может произойти, если в объекте есть ссылки на неуправляемые ресурсы, которые не были закрыты.

Проверьте ресурсы, используемые в этом классе. Некоторые из них должны быть еще открыты.

person Waldemar    schedule 05.07.2016

Нет. После завершения ваш объект все еще может иметь некоторые ссылки на неуправляемые ресурсы. Проверьте наличие внутренних утечек.

person Mikolaytis    schedule 05.07.2016