Подтвердить что ты не робот

С# Как отменить подписку на все обработчики событий из данного события?

Есть ли простой способ перебора всех обработчиков, подписанных на данное событие? Моя проблема заключается в том, что клиенты подписываются, но забывают отказаться от подписки, так что происходит утечка памяти. Мне нужно, чтобы объект мог отключить все обработчики его событий в методе Dispose, чтобы утечка не произошла - по крайней мере, не из-за событий.

4b9b3361

Ответ 1

Установите значение null для вашего события: MyEvent = null;

Но действительно лучше заставить клиентов отказаться от подписки на ваше мероприятие.

Ответ 2

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

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

  • Dusing Campbell имеет приятную .
  • Мне также понравился этот обзор в CodeProject, в котором обсуждаются большинство сценариев.
  • Слабые события также используются в WPF, но этот подход кажется немного сложным (для меня).

Ответ 3

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

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

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

Ответ 4

В момент написания наиболее точный ответ наименее популярен.

Вы можете аннулировать обработчик событий, но это будет заблокировано в любом случае после того, как его владелец будет забит - его не так, чтобы быть супер аккуратным, но, как говорит Алекс, это не там, где проблема.

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

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

http://weblogs.sqlteam.com/mladenp/archive/2007/10/24/C-Care-about-Event-Memory-Leaks-with-Delegate.GetInvocationList.aspx