2010-08-26 64 views
5

我有一个窗体,其中我动态加载多个用户控件。我处理每个控件的事件。用事件处理程序动态加载用户控件 - 取消注册

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

是否清除()函数取摆脱事件的护理或我应该做

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

之前我清除()面板的内容?

基本上,我正在寻找一种方式来动态加载用户控件,并处理他们的事件,而不会造成泄漏,当我摆脱他们。

谢谢!

编辑: 因为我的控件在页面中的Page_Init事件创建(每次,因为它们是动态加载),是正确地说,他们的寿命长度不能大于页面的寿命? 从我所了解的情况来看,该控件在发布后不存在。每次创建一个新的。因此,我不应该注销事件,因为它在下一页加载时甚至不存在。那是对的吗?

回答

5

该页面将坚持动态实例化控件的引用集合被清除后,也将阻止这些控件从收集到该页面本身收集。

在这种特殊情况下,这可以很好地工作,因为页面的寿命很短。

但是,如果这是一个Windows窗体应用程序,那么内存将有效泄露,直到表单被释放。

一般来说,当您释放事件发生的对象时,取消订阅您的事件是一个好主意,因为这是绝大多数.net内存泄漏的来源。

0

垃圾收集器应该能够收集他们没有你让他们注销

0

说出动态加载的usercontrols的使用寿命不能超过它所属的页面的寿命是正确的。但是,在从页面控件集合中删除Web控件并将其分配给例如会话变量的情况下,我们不能说这是真的,可能会导致Web控件的寿命比页面更长。所以它并不总是正确的。

如果您使用短生命的方法订阅长寿命对象的事件(例如单例对象或与应用程序一起存储的对象,会话和缓存),您应该取消订阅事件对象(如页面,用户控件或Web控件等)。

例如

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

这应该是从不会引起了内存泄漏的事件退订。

最后你不必担心在你的情况下注册的事件。他们将被垃圾收集器收集。

0

您在面板中调用controls.Clear的事实足以证明您还应注销事件。

为此,您可以使用重写的Clear方法中的未注册代码创建您自己的控件集合,而不是使用重写的Controls属性获取器返回的使用您的新集合创建自己的面板。

相关问题