Вопрос

Я использую несколько блюдных поведений и триггеров на серебряном управлении. Мне интересно, есть ли какой-либо механизм для автоматического отсоединения или обеспечения того, чтобы onDetaching () вызывается для поведения или триггера, когда управление больше не используется (то есть удалено из визуального дерева).

Моя проблема в том, что есть управляемая утечка памяти с контролем из-за одного из поведений. Поведение подписывается на мероприятие на некоторое длительно живущее объектом в оно в онопутном () и должно быть отписаться от этого события в OnDetaching () переопределении, чтобы он мог стать кандидатом на сбор мусора. Тем не менее, OnDetaching () никогда не вызывает, когда я удаляю контроль от визуального дерева ... единственный способ, которым я могу это произойти, это явно отсоединение проблемного поведения, прежде чем удалить контроль, а затем правильно собрано мусор Отказ

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

public void DetachBehaviors()
{
     foreach (var behavior in Interaction.GetBehaviors(this.LayoutRoot))
     {
          behavior.Detach();
     }

     //continue detaching all known problematic behaviors on the control....
}
Это было полезно?

Решение

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

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

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

К счастью, вам не нужно построить этот материал, сами, другие уже сделали это. Это называется WeakEventListener. Отказ Этот блог: Подчеркивая «слабый» вклад; Улучшения делают предотвращение утечек памяти с WeakeventListener еще проще! Имеет отличный набор ссылок на эту тему.

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

Джост Ван Шайка Предлагает альтернативный способ очистки ссылок из прилагаемого поведения, избегая проблемы с утечкой памяти. Это зависит от выполнения работой очистки с использованием делегатов загруженных и разгруженных событий AdvanceObject.

Он также предлагает кодовый фрагмент для создания заглушек для прилагаемого поведения.

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