我创建了一个包含两个表单的简单测试程序。一个包含一个按钮来启动过程并且只包含一个图像(或在另一个测试用例中包含一个byte [])。两者都包含一个允许渲染表单的计时器。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
timer1.Interval = 0;
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
private void timer1_Tick(object sender, EventArgs e)
{
// Instantiate and show Form2
timer1.Enabled = false;
var form2 = new Form2();
form2.ShowDialog();
// Dispose, force Collect and show (estimated) memory usage
form2.Dispose();
GC.Collect();
System.Diagnostics.Debug.WriteLine(GC.GetTotalMemory(true));
timer1.Enabled = true;
}
}
另一个Form只关闭自己(.designer-Part中有一个PictureBox):
public partial class Form2 : Form
{
// Alternative test
// private byte[] bytes;
public Form2()
{
InitializeComponent();
timer1.Interval = 0;
timer1.Enabled = true;
//bytes = new byte[1024*1024];
}
private void timer1_Tick(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Ignore;
}
}
要点是:Form2
到底是什么并不重要:内存使用率上升,一次我得到OutOfMemoryException(或者在PictureBox的情况下System.Exception
结束在
at Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
at System.Drawing.Bitmap._InitFromMemoryStream(MemoryStream mstream)
但这似乎是本机调用中的OutOfMemoryException,它没有被正确抛出。)
我不明白为什么。对Form2
的旧实例没有任何引用,我调用Dispose
但内存未释放。
我使用CF 3.5。
答案 0 :(得分:1)
好的,这里有很多东西在起作用:
timer1_Tick需要对表单的引用。只要有一个对定时器中的表单的引用和表单中指针的引用,GC(至少CF一个,我在常规Framework上测试了这个)就无法释放内存。
似乎不足以在表单上调用Dispose
。我还必须在Timer上调用Dispose来释放它的所有内存。 This is a bug.
public partial class Form2 : Form
{
private byte[] bytes;
public Form2()
{
InitializeComponent();
timer1.Interval = 0;
timer1.Enabled = true;
bytes = new byte[1024 * 1024];
}
private void timer1_Tick(object sender, EventArgs e)
{
this.DialogResult = DialogResult.Ignore;
this.timer1.Tick -= timer1_Tick;
this.timer1.Dispose();
this.mainMenu1 = null;
}
}