Интересное событие «Распоряжаться» поведением

Я заметил интересное поведение в нашем приложении .NET WinForms. У нас есть форма MDI, в которую добавлено много детей MDI. Эти дочерние формы прослушивают «трансляцию» событие, которое по сути является призывом обновить себя. Событие объявляется в базовом классе, а события прослушивания добавляются в дочерние формы.

Я заметил, что даже когда эти дочерние формы закрыты, события все еще обрабатываются, если событие явно не удалено в методе Dispose ().

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

Понимание будет высоко ценится.

(используя C #, .NET 3.5)

Ответы на вопрос(4)

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

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

WeakEvent шаблон был достигнут.

которое все еще находится в области видимости, поскольку оно находится в главной форме, все еще имеет ссылку на делегат в дочернем окне. Поэтому закрытие окна не приведет к удалению объекта, так как он также все еще находится в области действия этой ссылки. Это очень распространенный способ получить «утечку памяти» в .NET. Также учтите, что, поскольку дочернее окно все еще находится в области видимости, все внутри окна все еще находится в области видимости и также не будет собрано.

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

рассчитывает & quot; как ссылка на вашу детскую форму. (так что ваши дочерние формы также не собираются мусором).

Чтобы увидеть, что происходит, найдите справку о делегате. у него есть член с именем Target (типа object), который указывает на подписчика. Итак, у вас еще есть цепочка ссылок:

MDI Parent (издатель событий) - & gt; делегат - & gt; Ваша детская форма.

Вы должны очистить свои подписки на события в Dispose (), иначе ваши дочерние формы никогда не будут иметь права на сборку мусора.

Теперь, если вы посмотрите в Интернете на «события слабых ссылок», вы найдете множество обходных путей, которые люди опубликовали для определения слабых событий. Вот только один пример:http://www.codeproject.com/KB/cs/weakeventhandlerfactory.aspx

Мне также пришлось создать прототип, и я был бы рад поделиться им, если вы этого хотите. Тем не менее, мой совет - придерживаться регулярных событий и убирать в Dispose ().

Ваш ответ на вопрос