Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Отписывание от события

#c_sharp #net #события


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


Ответы

Ответ 1



Представим себе сценарий (пример того как не надо делать) : static class MyEventClass { public static event EventHandler someEvent; public static Delegate[] GetInvokationList() { return someEvent.GetInvocationList(); } } class MyClass { void someEvent_Handler(object sender, EventArgs e) { Console.WriteLine("hello"); } public MyClass() { MyEventClass.someEvent += someEvent_Handler; } } class Program { static void SomeMethod() { new MyClass(); } static void Main() { SomeMethod(); Delegate[] invokationList = MyEventClass.GetInvokationList(); for (int i = 0; i < invokationList.Length; i++) Console.WriteLine("Subscribed to event in {0} to handler {1}", invokationList[i].Target, invokationList[i].Method.Name); Console.ReadKey(); } } На экран получаем результат : Subscribed to event in Test.MyClass to handler someEvent_Handler Пояснение примера: В методе, где мы создаем объект этот объект должен был бы быть собранным сборщиком мусора по заверешнию метода, но мы подписали его метод к статическому ивенту, таким образом создали ссылку на него. Именно поэтому он не будет собран сборщиком мусора пока не закончится работа программы и сборщик мусора не соберет класс-объект в котором хранится ссылка на этот класс... Наш класс с событием был статическим, но то же происходило бы и с нестатическим классом. Если бы мы отписались от события вовремя - то такой проблемы бы не возникло. По возможности нужно избегать статические события вообще так как они ведут к "memory leak", но если уж придется - лучше класс наследовать от интерфейса IDisposable и в методе Dispose() отписываться от всех событий... Потом создавать экземпляр класса только используя директиву using, например : class MyClass : IDisposable { public void Dispose() { MyEventClass.someEvent1 -= someEvent_Handler1; MyEventClass.someEvent2 -= someEvent_Handler2; MyEventClass.someEvent3 -= someEvent_Handler3; } } И в программе : using(MyClass instance = new MyClass()) { // code here }

Ответ 2



Нужно не null присваивать, а использовать оператор -= my.MyEvent -= MyEventHandle();

Комментариев нет:

Отправить комментарий