2013-03-12 2 views
3

В следующей программе ...Вывоз мусора из неиспользуемых объектов с обработчиком событий живого

using System; 

class Program 
{ 
    static Parent parent; 

    static void Main(string[] args) 
    { 
     parent = new Parent(); 
     // The program hereafter runs for a long time and occasionally 
     // causes parent.SomeEvent to be raised. 
    } 
} 

class Parent 
{ 
    public event EventHandler SomeEvent; 

    public Parent() 
    { 
     new Handler(this); 
    } 
} 

class Handler 
{ 
    public Handler(Parent parent) 
    { 
     parent.SomeEvent += parent_SomeEvent; 
    } 

    void parent_SomeEvent(object sender, EventArgs e) 
    { 
     // Does something important here. 
    } 
} 

Обратите внимание, что экземпляр Handler объект не ссылается, хотя он подписался SomeEvent. Возможно ли, что после того, как программа будет работать некоторое время, сборщик мусора может решить исключить экземпляр Handler, и его обработчик parent_SomeEvent, следовательно, больше не будет вызываться всякий раз, когда поднимается parent.SomeEvent?

Мне нужно это пояснение для приложения, которое я пишу. Есть много Handler-подобных объектов, которые создаются, как показано выше, без ссылки. Основной целью Handler является подписка на SomeEvent. Нет никаких полезных методов для вызова ссылки на экземпляр Handler, поэтому я был бы в порядке, не ссылаясь на него иначе. Во время отладки я не сталкивался с какими-либо проблемами. Но теперь я обеспокоен тем, что проблемы могут возникнуть после развертывания, когда приложение работает в течение длительного времени, а сборщик мусора более активен.

+0

Отметьте это сообщение http://stackoverflow.com/questions/4526829/why-and-how-to-avoid-event-handler-memory-leaks для углубленного объяснения – Osiris

ответ

3

При запуске программы, то Parent класс содержит ссылку на экземпляр EventHandler делегата, который вы создаете в Handler конструктора, а экземпляр делегата содержит ссылку на экземпляр Handler. Таким образом, экземпляр Handler не будет собирать мусор, пока есть ссылка на экземпляр Parent.

6

Объект вашего класса Handler не будет собирать мусор, пока все ссылки на этот объект не будут удалены.

Таким образом, пока вы не отпишете все обработчики событий, объект будет жить. Поскольку подписанный обработчик событий также является еще одной «ссылкой», которая соединяет экземпляр Parent с экземпляром Handler.

Возможно ли, что после того, как программа работает на некоторое время, сборщик мусора может принять решение о ликвидации экземпляра Handler и его обработчик parent_SomeEvent не будет поэтому больше не будет вызываться всякий раз parent.SomeEvent поднят?

Именно по этой причине GC собирает только «неопубликованные» объекты из кучи. Ваш сценарий приведет к неопределенным NullReferenceException s, полностью зависящим от того, когда GC решит удалить объекты. Так, к счастью, это не так :).

Кроме того, GC является достаточно интеллектуальным, чтобы определять изолированные пулы неопознанных объектов (неописанные острова). Таким образом, в сценарии ваш родительский объект также не получает ссылок, поскольку GC определит, что целая цепочка объектов не была найдена (объект Parent, event и объект handler) и собирает их все вместе в следующем цикле сбора.

Если возможно, я бы рекомендовал статью this MSDN. Дает вам хороший обзор широкой концепции сбора мусора в .NET. Очень полезно иметь в виду во время кодирования.

4

Программа существует все время, и это имеет в виду экземпляр Родитель, и, таким образом, Родитель никогда не будет мусора (пока программа не закончится).

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

Итак, в общем, нет, это не будет сбор мусора.

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