Останавливают ли обработчики событий сборку мусора?

Если у меня есть следующий код:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

Будет ли pClass собираться мусором? Или он будет торчать и запускать свои события всякий раз, когда они происходят? Нужно ли мне сделать следующее, чтобы разрешить сборку мусора?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;

Я собираюсь предварительно предложить читателям, интересующимся этим вопросом, возможно, стоит ознакомиться с легковесными событиями / шаблонами слабых событий, которые НЕ предотвращают сборку мусора. Хорошая начальная загрузка SO для этой темы - stackoverflow.com/questions/185931/…

fostandy 13.05.2010 10:36

Примечание для потомков: установка для ссылки значения null просто задерживает сборщик мусора, расширяя на одну строку область действия ссылки. .NET - это не VB6.

John Saunders 13.12.2011 07:51
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
187
2
28 847
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Для конкретного вопроса «Будет ли pClass сборщиком мусора»: подписка на событие не влияет на сборку pClass (как издателя).

Для GC в целом (в частности, цели): это зависит от того, является ли MyFunction статической или основанной на экземпляре.

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

Обратите внимание, что это односторонний; т.е. если у нас есть:

publisher.SomeEvent += target.SomeHandler;

тогда "издатель" будет поддерживать "цель" в живых, но "цель" не будет поддерживать "издателя".

Итак, нет: если pClass все равно будет собираться, нет необходимости отменять подписку на слушателей. Однако, если pClass был долгоживущим (дольше, чем экземпляр с MyFunction), то pClass мог бы поддерживать этот экземпляр живым, поэтому бы необходимо для отказа от подписки, если вы хотите, чтобы цель была собрана.

Однако по этой причине статические события очень опасны при использовании с обработчиками на основе экземпляров.

Что ж, если вопрос: «Будет ли pClass собираться мусором?», То ответ «это зависит от того, будет ли ...» на самом деле неверен. Это ни от чего не зависит, как отмечает далее сам Марк.

Tor Haugen 18.11.2008 13:09

@Tor - честно - поясню

Marc Gravell 18.11.2008 13:54

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

supercat 13.04.2012 19:37

Отличный ответ, потому что он также обращается к другой половине вопроса (который не задавался): издатель остановит сборку подписчик.

Bob Sammers 23.06.2017 21:12

Да, и как сказал @BobSammers, это действительно может быть проблемой, если экземпляр с коротким сроком службы, такой как форма / окно, подписывается на долгоживущий сервис, такой как синглтон, который предоставляет данные, например: синглтон затем сохраняет ссылку , и объекты поэтому сохраняются в памяти, даже если мы думаем, что они выгружены! Поэтому будьте очень осторожны при использовании событий. Мы злоупотребляли событиями для нашего большого ПО, и потом это очень сложно решить.

Elo 28.03.2018 16:11

Да, pClass будет удален сборщиком мусора. Подписка на событие не означает, что существует какая-либо ссылка на pClass.

Итак, нет, вам не придется отсоединять обработчик, чтобы pClass был собран сборщиком мусора.

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

Если вы не уверены, что что-то будет собрано, задайте себе следующий вопрос: существует ли еще ссылка на это? На обработчики событий ссылается экземпляр объекта, а не наоборот.

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

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