Как встроенные элементы управления WPF управляют своими обработчиками событий для прикрепленного события? - PullRequest
5 голосов
/ 09 февраля 2009

Я знаю, что когда вы регистрируете объект для прикрепленных событий мыши, у вас возникают утечки памяти. Вот почему вам нужно использовать WeakEvent pattern .

У меня проблема с этим шаблоном: если вы хотите использовать его, вы не можете определить свой обработчик в коде XAML.

Для меня это означает, что каждый подобный код просачивается:

<SomeControl Mouse.MouseDown="MyHandler" />

Если вы явно не удалите свой обработчик в коде (и я сомневаюсь, что кто-нибудь так поступит). Теперь есть кое-что, чего я не понимаю:

<Button Click="MyHandler" />

Этот код где-то использует событие Mouse.MouseDown, чтобы обнаружить нажатие кнопки. Проведя некоторые исследования с отражателем, я обнаружил, что это событие использует MouseDown класса UIElement. И когда я читаю код UIElement, я не понимаю: WeakEventManager не существует!

Может кто-нибудь объяснить мне, как UIElement получает события от Mouse.MouseDown без утечки?

1 Ответ

7 голосов
/ 10 февраля 2009

Использование обычных обработчиков в XAML не требует слабых ссылок.

То, что вы делаете, - это создание ссылки на память между основным и дочерним элементами управления, содержащимися в этом элементе управления; дочерний элемент управления в этом случае - кнопка.

Если кто-то поддерживает ссылку на какую-либо часть визуального дерева для основного элемента управления, все дерево останется в памяти, потому что оно связано (родительские / дочерние ссылки).

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

Обработчики событий в XAML создают только внутренние ссылки на события.

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

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

...