主窗口:
namespace WindowsFormsApplication17
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public event EventHandler Form1Test;
private void button1_Click(object sender, EventArgs e)
{
var sb = new StringBuilder();
sb.AppendLine(GetTotalMemory());
for (int i = 0; i < 5; i++)
{
var form2 = new Form2() { Parent = this };
form2.Form2Test += new EventHandler(form2_Form2Test); // register event in Form2 doesn't cause memory leak.
form2.Show();
form2.Close();
GC.Collect();
sb.AppendLine(GetTotalMemory());
}
MessageBox.Show(sb.ToString());
}
void form2_Form2Test(object sender, EventArgs e)
{
}
public static string GetTotalMemory()
{
// bytes in current process' managed heap.
return GC.GetTotalMemory(true) / 1024 + " K";
}
}
}
子窗口:
namespace WindowsFormsApplication17
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private byte[] strs = new byte[50 * 1024 * 1024]; // 50MB
//You can very well make a static
//member eligible for a collection by setting it to null. Otherwise, a static
//member would last for the life of the appdomain in which it lies.
private static byte[] strss = new byte[20 * 1024 * 1024]; // 20MB
public event EventHandler Form2Test;
public Form1 Parent { get; set; }
protected override void OnLoad(EventArgs e)
{
Parent.Form1Test += new EventHandler(Form2_Form1Test);
base.OnLoad(e);
}
void Form2_Form1Test(object sender, EventArgs e)
{
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
// if don't unregister this event from parent, causes memory leak.
Parent.Form1Test -= new EventHandler(Form2_Form1Test);
}
}
}
静态字段strss在调用了GC.Collect();后还是存在的,它不会被回收。
在子form中注册父form的事件,如果不取消注册会导致内存泄露。
相反,在父form中注册子form的事件,不会导致内存泄露。
如果注释掉Parent.Form1Test -= new EventHandler(Form2_Form1Test);
运行结果如下,内存泄露了:
如果执行这句代码,运行结果如下,内存不泄露: