Динамически загружаемый пользовательский элемент управления с обработчиками событий - отменить регистрацию - PullRequest
5 голосов
/ 27 августа 2010

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

UserControl userControl1 = LoadControl("control.ascx") as UserControl;
userControl1.Event += new ControlEventHandler(userControl_Event);
this.Panel.Controls.Add(userControl1);

UserControl userControl2 = LoadControl("control.ascx") as UserControl;
userControl2.Event += new ControlEventHandler(userControl_Event);
this.Panel.Controls.Add(userControl2);

...

Теперь, когда я избавляюсь от элементов управления на панели, я просто делаю

this.Panel.Controls.Clear();

Функция Clear () заботится о том, чтобы избавиться от событий, или я должен делать

foreach(Control control in this.Panel.Controls)
{
    UserControl userControl = control as UserControl;
    if(userControl != null)
    {
        userControl -= userControl_Event;
    }
}

до того, как я очистил () содержимое панели?

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

Спасибо!

EDIT: Поскольку мои элементы управления создаются в событии Page_Init на странице (каждый раз, когда они загружаются динамически), правильно ли говорить, что срок их службы не может превышать срок жизни страницы? Из того, что я понимаю, контроль не существует после поста назад. Новый создается каждый раз. Поэтому мне не нужно отменять регистрацию события, потому что объект, которого он даже не существует, загружается на следующей странице. Это правильно?

Ответы [ 5 ]

5 голосов
/ 01 сентября 2010

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

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

Однако, если бы это было приложение для Windows Form, то память фактически просочилась бы, пока форма не была выпущена.

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

2 голосов
/ 01 сентября 2010

Эта страница на MSDN отвечает на ваш вопрос:

Control .. ::. ControlCollection .. ::. Clear Метод

Цитируя это:

Важно

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

0 голосов
/ 06 сентября 2010

Тот факт, что вы вызываете controls.Clear на панели, является достаточным доказательством того, что вам также следует отменить регистрацию событий.

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

0 голосов
/ 01 сентября 2010

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

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

Например

UserControl uc = LoadControl("control.ascx") as UserControl;
SomeObject so=Session["SomeObject"] as SomeObject;
If(so!=null)
{
    so.SomeEvent += new SomeEventHandler(uc.SomeMethod);
}

Здесь следует отписаться от события, чтобы не вызвать утечку памяти.

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

0 голосов
/ 31 августа 2010

Сборщик мусора должен иметь возможность собирать их без необходимости отмены регистрации

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...