Ist*_*tel 8 c# memory events memory-leaks
我将创建一个GUI,它将动态创建控件集,并为其分配事件.我需要在运行时添加和删除这些控件.它看起来像这样:
FlowLayoutPanel.Controls.Clear();
<< add new controls, assigning Click events with += >>
Run Code Online (Sandbox Code Playgroud)
我听说用+ =分配事件处理程序会导致内存泄漏(更具体地说,在应用程序退出之前不会释放内存).我想避免这种情况.我知道我可以写一些像这里的函数如何从控件中删除所有事件处理程序以查找所有事件处理程序并删除它们但它看起来非常复杂.
还有另外一种方法吗?调用Dispose有助于删除那些事件处理程序吗?你能破坏对象来强制释放内存,就像在C/C++中一样吗?
谢谢!
PS:问题是,我不知道要分离的事件.我将创建大量标签并向其添加不同类型的onclick事件.当它清理流布局面板时,无法知道哪个事件处理程序附加到哪个标签.
这是示例代码(_flowLP是FlowLayoutPanel) - 此Refresh()函数在应用程序退出之前多次运行.
private void Refresh()
{
Label l;
Random rnd = new Random();
// What code should i add here to prevent memory leaks
_flowLP.Controls.Clear();
l = new Label();
l.Text = "1";
if (rnd.Next(3) == 0) l.Click += Method1;
if (rnd.Next(3) == 0) l.Click += Method2;
if (rnd.Next(3) == 0) l.Click += Method3;
_flowLP.Controls.Add(l);
l = new Label();
l.Text = "2";
if (rnd.Next(3) == 0) l.Click += Method1;
if (rnd.Next(3) == 0) l.Click += Method2;
if (rnd.Next(3) == 0) l.Click += Method3;
_flowLP.Controls.Add(l);
l = new Label();
l.Text = "3";
if (rnd.Next(3) == 0) l.Click += Method1;
if (rnd.Next(3) == 0) l.Click += Method2;
if (rnd.Next(3) == 0) l.Click += Method3;
_flowLP.Controls.Add(l);
l = new Label();
l.Text = "4";
if (rnd.Next(3) == 0) l.Click += Method1;
if (rnd.Next(3) == 0) l.Click += Method2;
if (rnd.Next(3) == 0) l.Click += Method3;
_flowLP.Controls.Add(l);
l = new Label();
l.Text = "5";
if (rnd.Next(3) == 0) l.Click += Method1;
if (rnd.Next(3) == 0) l.Click += Method2;
if (rnd.Next(3) == 0) l.Click += Method3;
_flowLP.Controls.Add(l);
l = new Label();
l.Text = "6";
if (rnd.Next(3) == 0) l.Click += Method1;
if (rnd.Next(3) == 0) l.Click += Method2;
if (rnd.Next(3) == 0) l.Click += Method3;
_flowLP.Controls.Add(l);
}
Run Code Online (Sandbox Code Playgroud)
当您将生命周期较短的事件使用者附加到生命周期较长的事件生产者时,这主要是一个令人担忧的问题。如果他们有相似的生活或者与我所描述的相反,那不是问题。
如果您确实担心这一点,只需使用 -= 与事件分离。这会删除附件创建的引用,并有助于避免此类内存问题。
编辑:由于评论有点长,我将在这里发布一些后续内容。当您附加到一个事件时,您所做的就是在事件提供者上挂起对您自己的引用。因此,举例来说,如果您有一个带有 StrikesMidnight 事件的 Clock 类,并且您从名为 Bedtime 的类中订阅了该事件,则 Bedtime 的实际机制clock.StrikesMidnight += this.HandleMidnight;
是您为自己分配了一个对 Clock 的引用。就好像 Clock 有一个对象属性,而你说clock.ObjectProperty = this;
因此,在 Bedtime 类的生命周期很短并且超出范围的情况下,Bedtime 会出现,在 Clock 上挂起对其自身的引用,然后超出范围。问题是,时钟仍然有对它的引用,所以即使它超出了范围,垃圾收集器也不会收集就寝时间。
....
这就是背景。在您的情况下,您正在创建一个标签并将对您自己的引用附加到它(通过您的“MethodX”处理程序)。调用刷新时,您将清除标签列表(意味着它们超出范围)。它们超出了范围,并且通过 MethodX 处理程序引用了您的类,但那又怎样呢?它们具有引用并不会阻止它们被 GC 回收。没有人在您的代码中保存对它们的引用,因此 GC 将对它们进行工作,并且您不会泄漏内存。
归档时间: |
|
查看次数: |
774 次 |
最近记录: |