При каких обстоятельствах нам нужно дважды вызвать GC.Collect - PullRequest
9 голосов
/ 30 сентября 2010

У нас есть приложение WPF, основанное на Unity с шаблоном MMVVVM. В жизненном цикле приложения может быть несколько жизненных циклов проекта, после каждого жизненного цикла проекта мы делаем Tear Down вручную и пытаемся освободить все ссылки на ViewModels. Для подписок на события с Unity мы используем Слабые ссылки. Таким образом, мы предполагаем, что после разрыва мы можем вызвать GC Collect, чтобы все объекты мусора собирались мусором. У нас есть еще один вариант, чтобы вручную отменить подписку на все события, но мы предпочитаем сборку мусора, потому что она очистит около 200 МБ, что облегчит загрузку нового проекта.

В одном случае мы наблюдаем, что, если я вызову GC.Collect только один раз, его ссылка все еще останется в памяти на некоторое время.

GC.Collect();
GC.WaitForPendingFinalizers(); 

Но если я попытаюсь вызвать GC два раза подряд, он все прекрасно очистит.

GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();

Любые мысли или указатели будут высоко оценены.

Обновление:

В классе не определены финализаторы.

Теперь я также рассматриваю случай, когда этот объект упоминается в другом объекте, который может иметь финализатор. В нашей среде у нас есть финализатор только для DBProvider, поэтому я не думаю, что даже в этом случае.

Ответы [ 4 ]

11 голосов
/ 30 сентября 2010

Похоже, у вас есть что-то с финализатором, в основном - если вы вызываете GC.Collect() только один раз, финализаторы заканчиваются, но завершенные объекты не собираются.

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

6 голосов
/ 30 сентября 2010

Если я вызываю GC.Collect только один раз, его ссылка все еще остается в памяти на некоторое время.

Не очень странно.Когда у объекта есть финализатор (и GC.SuppressFinalize () для него не был вызван), он получает приостановку выполнения (он не собран, так что финализатор может работать с действительными объектами).Все экземпляры, на которые ссылается этот объект, также получают приостановку исполнения.Второй цикл через GC необходим, чтобы очистить все это.

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

после каждого жизненного цикла проекта мы делаем руководство Tear Down

Звучит сложно и легко избежать ... Сколькоесть ссылки в модели вашего домена / вида?В идеале вы должны просто вырезать 1 или 2 ссылки на «основной» объект и забыть об этом.

0 голосов
/ 12 апреля 2016

У вас слабая ссылка, которую вы ожидаете установить равной нулю, когда вы звоните в GC, и вы верите, что ничто не поддерживает объект в живых.

Я не знаю, как слабые ссылки реализованы в .net, но очень возможно, что они задерживают сбор объектов и используют такую ​​систему, как финализаторы.

Или, возможно, у вас есть объект, который необходимо завершить, поскольку вы не вызывали dispose () для него. (Очень часто встречается в WPF или WinForms)

Чтобы выяснить это, вам нужно использовать MemoryProfiler, рассчитывая потратить, по крайней мере, один день на изучение того, как использовать любой профилировщик памяти, поскольку вам будет представлено много данных об объектах, внутренних для WPF. Лично я бы скачал бесплатный след Профилировщик памяти Redgate и попытался бы выяснить, в чем проблема, там поддержка также полезна. (Другие профилировщики памяти также работают хорошо, в значительной степени это зависит от того, к чему вы привыкли.)

0 голосов
/ 01 октября 2010

@ Нитин, я не уверен, поможет ли мое предложение вам или нет, но, как правило, мы должны избегать явного вызова GC.Collect (). потому что это может вызвать проблемы с производительностью. Вместо этого попробуйте следовать правильной схеме утилизации.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...