Как отцепить обработчики событий в C#
Я работаю над приложением C#, которое имеет несколько форм.
Когда я открываю одну из форм, я добавляю прослушиватель событий следующим образом: SomeClass.MotionCompleted += new EventHandler(HandlerMethod);
, Событие MotionCompleted является статическим событием.
Я заметил, что после закрытия этой формы HandlerMethod по-прежнему вызывается, когда происходит событие, которое затем вызывает исключение, потому что он пытается обновить что-то в форме, которая больше не существует.
Как может EventListener существовать и реагировать на событие, даже если форма больше не существует? Когда вызывается form.Close() или this.Close(), разве это не должно автоматически отсоединять списки событий, чтобы они больше не вызывались?
9 ответов
Это зло статических событий!:) У тебя там есть утечка.
Отмените OnClosing вашей формы и отмените регистрацию вашего обработчика:
protected override void OnClosing(CancelEventArgs e) {
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
}
Someclass.MotionCompleted -= new EventHandler(HandlerMethod);
В этой статье показано множество советов, касающихся событий в C#: http://www.yoda.arachsys.com/csharp/events.html
Чтобы добавить ко всем дублирующимся ответам, вы также можете отцепить этот путь:
SomeClass.MotionCompleted -= HandlerMethod;
Выходной код сборки будет таким же, используете ли вы -= HandlerMethod
или же -= new EventHandler(HandlerMethod)
,
Вы должны отцепить вручную:
SomeClass.MotionCompleted -= HandlerMethod;
Вам необходимо вручную отцепить событие следующим образом: SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
События являются сильной ссылкой: они не могут быть собраны мусором, если вы явно не разыграете их.
Вот почему я предлагаю вам использовать методы подписки и рассылки, которые будут выполнять свою работу и централизовать эти хуки (что приведет к утечкам памяти, если вы их не освободите)
private void subscribeAll()
{
SomeClass.MotionCompleted += new EventHandler(HandlerMethod);
// other subscription
}
private void unSubscribeAll()
{
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
// other subscription
}
Вы можете использовать этот пример кода:
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
Однако вы должны быть осторожны, чтобы отцепить ваше событие от того же экземпляра объекта, содержащего HandlerMethod
тот, который зарегистрировал это.
Не совсем. Форма не собирается сборщиком мусора, потому что обработчик событий все еще там. Обработчики статических событий сами по себе не отцепляются. Вы можете отцепить любое назначенное событие в форме метода onClosing, например:
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
После этого все должно работать.
SomeClass.MotionCompleted -= new EventHandler(HandlerMethod);
просто измените "+" на "-"