Вопрос

У меня есть приложение WindowsForms, из-за которого происходит утечка памяти, поэтому я использовал профилировщик памяти ANTS от Redgate, чтобы просмотреть объекты, которые, как я подозреваю, и обнаружил, что они удерживаются только объектами, уже находящимися в Очередь финализатора.Отлично, а что такое очередь финализатора?Можете ли вы указать мне на лучшее определение?Можете ли вы поделиться каким-нибудь анекдотическим советом?

Кроме того, все корневые объекты GC в очереди финализатора являются экземплярами System.Windows.Forms.Control+ThreadMethodEntry объекты с именем «вызывающий».Я вижу, что он участвует в многопоточном взаимодействии пользовательского интерфейса, но кроме этого я мало что знаю.Простите мою кажущуюся лень и невежество, но все эти ресурсы скрыты внутри компонентов поставщика.Я разговариваю с поставщиком по этим вопросам, но мне нужно какое-то направление, чтобы я мог ускорить разговор.Можете ли вы указать мне наиболее полезное определение ThreadMethodEntry?Есть какой-нибудь анекдотический совет?

Кроме того, стоит ли мне вообще беспокоиться об этих объектах в очереди финализатора?

Обновлять: Этот Статья о Красных воротах было полезно.

Это было полезно?

Решение

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

Если вы раньше работали с утечками памяти, то видеть кучу объектов вашего поставщика в очереди финализатора может быть небрежным кодом, но это не указывает на утечку памяти.Обычно хороший код предоставляет метод Dispose, который собирает как управляемые, так и неуправляемые ресурсы, и при этом удаляет себя из очереди финализатора через GC.SuppressFinalize().Итак, если объекты поставщика реализуют метод Dispose, а ваш код его не вызывает, это может привести к появлению множества объектов в очереди финализатора.

Пробовали ли вы создать в ANTS снимок между двумя моментами времени и сравнить объекты, созданные между ними?Это может помочь вам выявить утечку управляемых объектов.

Кроме того, если вы хотите увидеть, исчезает ли память при запуске финализаторов, попробуйте это просто для проверки:

System.GC.Collect();
System.GC.WaitForPendingFinalizers(); // this method may block while it runs the finalizers
System.GC.Collect();

Я не рекомендую запускать этот код в обычном режиме.Возможно, вам захочется запустить его, если вы только что проделали массу работы и создали много мусора.Например, в нашем приложении одна из наших функций может создать около 350 МБ мусора, который теряется после закрытия окна MDI.Поскольку известно, что при этом остается много мусора, мы принудительно собираем мусор вручную.

Также обратите внимание, что в базовом коде Windows.Forms имеется низкоуровневый кеш свойств, который будет хранить последнее открытое модальное диалоговое окно.Это может быть источником утечки памяти.Один из надежных способов избавиться от этой ссылки — вызвать другое простое диалоговое окно, а затем запустить приведенный выше код GC.

Другие советы

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

Класс ThreadMethodEntry является реализацией IAsyncResult, и экземпляры этого класса обычно создаются при вызове асинхронных операций, таких как использование Invoke для обновления пользовательского интерфейса или использование методов Begin*/End*.

Вот хороший пост в блоге, в котором описывается аналогичная проблема.На более техническом уровне вы можете использовать SOS.dll (описанный в сообщении блога) и Sosex.dll чтобы помочь вам понять, почему эти объекты ThreadMethodEntry зависают в памяти.В этих расширениях WinDbg есть команды, которые могут отслеживать, какие другие объекты ссылаются на определенный объект в памяти.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top