简体   繁体   English

使用事件处理程序动态加载用户控件 - 取消注册

[英]Dynamically loaded user control with Event Handlers - Unregister

I have a form with a panel on which I dynamically load multiple user controls. 我有一个带有面板的表单,我可以动态加载多个用户控件。 I handle events for each of these controls. 我为每个控件处理事件。

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);

...

Now when I get rid of the controls on the Panel, I simply do a 现在,当我摆脱Panel上的控件时,我只是做了一个

this.Panel.Controls.Clear();

Does the Clear() function take care of getting rid of the events or should I be doing Clear()函数是否负责摆脱事件或我应该做什么

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

before I Clear() the content of the Panel? 在我清除()小组的内容之前?

Basically, i'm looking for a way to load user controls dynamically and handle their events without creating a leak when I get rid of them. 基本上,我正在寻找一种方法来动态加载用户控件并处理他们的事件,而不会在我摆脱它们时造成泄漏。

Thanks! 谢谢!

EDIT: Because my controls are created in the Page_Init event of the page (each time, as they are loaded dynamically), is it correct to say that their lifespan cannot be longer than the page's lifespan? 编辑:因为我的控件是在页面的Page_Init事件中创建的(每次都是动态加载的),说它们的生命周期不能超过页面的生命周期是否正确? From what I understand, the control doesn't exist after a post back. 根据我的理解,回发后控件不存在。 A new one is created each time. 每次都会创建一个新的。 Therefore, I shouldn't have to unregister the event because the object it doesn't even exist on the next page load. 因此,我不应该取消注册该事件,因为它在下一页加载时甚至不存在该对象。 Is that correct? 那是对的吗?

The page will hold references to the dynamically instantiated controls even after the collection has been cleared, which will prevent the controls from being collected until the page is itself collected. 即使在清除了集合之后,该页面也将保留对动态实例化控件的引用,这将阻止在页面本身被收集之前收集控件。

In this particular situation this will work out fine because the life of the page is very short. 在这种特殊情况下,这将很好,因为页面的生命周期很短。

However, if this were instead a windows forms app, then the memory would effectively be leaked until the form was released. 但是,如果这是一个Windows窗体应用程序,那么内存将被有效泄露,直到窗体被释放。

In general it is a good idea to unsubscribe your events when you release the objects that the events go to, as this is the source of the vast majority of .net memory leaks. 通常,在释放事件所针对的对象时,最好取消订阅事件,因为这是绝大多数.net内存泄漏的来源。

This page on MSDN answers your question: MSDN上的这个页面回答了你的问题:

Control..::.ControlCollection..::.Clear Method Control .. ::。ControlCollection .. ::。Clear Method

Quoting it: 引用它:

Important 重要

Calling the Clear method does not remove control handles from memory. 调用Clear方法不会从内存中删除控制句柄。 You must explicitly call the Dispose method to avoid memory leaks. 您必须显式调用Dispose方法以避免内存泄漏。

垃圾收集器应该能够收集它们,而无需注销它们

It is correct to say that lifespan of usercontrols that are dynamically loaded cannot be live longer than the page it belongs. 可以肯定地说,动态加载的用户控件的生命周期不能超过它所属的页面。 But we cannot say this true in the case of removing a web control from the page control collection and assigning it to a, for example, session variable may cause web control having longer lifespan than page. 但是,在从页面控件集合中删除Web控件并将其分配给例如会话变量的情况下,我们不能说这是真的,这可能导致Web控件具有比页面更长的生命周期。 So it is not always correct. 所以它并不总是正确的。

It is important that you should unsubscribe from an event if you subscribe to a long life object's event (such as singleton object or objects stored with application, session and cache in the asp.net) with a method of a short life object (such as page, usercontrol or web control etc). 如果您使用短生命对象的方法订阅长寿命对象的事件(例如单个对象或与asp.net中的应用程序,会话和缓存一起存储的对象),则应取消订阅事件,这一点很重要(例如页面,用户控件或Web控件等)。

For example 例如

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

Here it should be unsubscribed from the event for not to cause a memory leak. 这里应该取消订阅事件,以免造成内存泄漏。

Eventually you dont have to worry about the registered events in your case. 最终你不必担心你的案件中的注册事件。 They will be collected by the garbage collector. 它们将由垃圾收集器收集。

The fact that you call controls.Clear in the panel is evidence enough that you should also unregister the events. 您在面板中调用controls.Clear这一事实足以证明您还应取消注册事件。

To do that, you could create your own control collection, with the unregistration code in the overridden Clear method, than create your own panel that uses your new collection, returned from an overridden Controls property getter. 为此,您可以创建自己的控件集合,使用重写的Clear方法中的取消注册代码,而不是创建自己的使用新集合的面板,从重写的Controls属性getter返回。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM