2009-05-29 1 views
5

В одном классе ClassA у меня есть объект таймера. В этом классе я регистрирую обработчики событий для прошедшего таймер события. В другом классе ClassB у меня есть открытый обработчик событий для прошедшего таймер события. Поэтому я зарегистрировать событие-обработчик из ClassB в ClassA следующим образом:Что происходит, когда событие срабатывает и пытается выполнить обработчик событий в объекте, который больше не существует?

myTimer.Elapsed += ClassBInstance.TimerElapsed 

Что произойдет, если я создать новый экземпляр ClassBInstance и таймер истек пожары событий, когда предыдущий экземпляр обработки события ClassB по-прежнему привязано к истекшему событию таймера?

Например:

ClassB classBInstance = new ClassB(); 
myTimer.Elapsed += classBInstance.TimerElapsed 

classBInstance = new ClassB(); 
myTimer.Elapsed += classBInstance.TimerElapsed 

ответ

10

AFAIK, ClassBInstance не мусор, пока есть события, зарегистрированные, поскольку событие содержит ссылку на него.

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

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

+5

Действительно. В частности, именно поэтому статические события настолько опасны; очень легко сохранить огромное количество объектов в живых, если вы не откажетесь от подписки религиозно. По крайней мере, события экземпляра умирают с экземпляром, который поддерживает поле поддержки, но не GC для статики. –

+0

Также стоит упомянуть, что WPF прыгает через обручи, чтобы избежать этого с WeakEvents, которые IMHO слишком сложны и нуждаются в некоторой языковой поддержке. – Josh

2

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

3

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

Конечно, это также означает, что вы должны отключить подписчиков, если хотите, чтобы их очищали независимо от издателя.

0

Вы можете использовать мой WeakEventHandler, основанный на WeakReference. Поскольку он сохраняет слабую ссылку на прослушиватель событий, он не заставляет слушателя жить.

see this answer

Смежные вопросы