EDIT - nulled thread before measuring finishing memory
This is all running .NET Compact Framework 2.0 under Windows CE 5.0.
I've come across some interesting behaviour in developing my App. Whenever I try to create a form and have it run a separate thread it seems to leak 392 bytes when it's closed and I'm unsure why.
My approach so far has been create a new thread and have it a) Create the form and continuously call Application.DoEvents until it shuts or b) Create the form pass it to Application.Run(Form).
The following is a sample form that illustrates the problem.
public partial class TestForm : Form
{
public TestForm()
{
InitializeComponent();
}
private void DoMemoryTest(bool useApplicationRun)
{
GC.WaitForPendingFinalizers();
GC.Collect();
long originalMem = GC.GetTotalMemory(true);
Thread t;
if (useApplicationRun)
t = new Thread(new ThreadStart(AppRunThread));
else
t = new Thread(new ThreadStart(DoEventThread));
t.Start();
Thread.Sleep(3000);//Dodgey hack
t.Join();
t = null;
GC.WaitForPendingFinalizers();
GC.Collect();
long terminatingMem = GC.GetTotalMemory(true);
MessageBox.Show(String.Format("An increase of {0} bytes was measured from {1} bytes",
terminatingMem - originalMem, originalMem));
}
private void button1_Click(object sender, EventArgs e)
{
DoMemoryTest(false);
}
private void button2_Click(object sender, EventArgs e)
{
DoMemoryTest(true);
}
private void AppRunThread()
{
Application.Run(new OpenCloseForm());
}
private void DoEventThread()
{
using (OpenCloseForm frm = new OpenCloseForm())
{
frm.Show();
do
{
Application.DoEvents();
} while (frm.Showing);
}
}
/// <summary>
/// Basic form that opens for a short period before shutting itself
/// </summary>
class OpenCloseForm : Form
{
public OpenCloseForm()
{
this.Text = "Closing Soon";
this.Size = new Size(100, 100);
this.TopMost = true;
}
public volatile bool Showing = false; //dodgy hack for DoEventThread
System.Threading.Timer timer;
protected override void OnLoad(EventArgs e)
{
Showing = true;
base.OnLoad(e);
timer = new System.Threading.Timer(new TimerCallback(TimerTick), null, 1000, 1000);
}
delegate void CloseDelegate();
private void TimerTick(object obj)
{
this.Invoke(new CloseDelegate(this.Close));
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
Showing = false;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
if (timer != null)
{
timer.Dispose();
timer = null;
}
}
base.Dispose(disposing);
}
}
//Designer code to follow....
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.timer1 = new System.Windows.Forms.Timer();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(32, 47);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(116, 39);
this.button1.TabIndex = 1;
this.button1.Text = "DoEvents Loop";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(32, 115);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(116, 39);
this.button2.TabIndex = 2;
this.button2.Text = "Application.Run";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// TestForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.AutoScroll = true;
this.ClientSize = new System.Drawing.Size(177, 180);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "TestForm";
this.Text = "TestForm";
this.TopMost = true;
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
}
Am I missing something in regards to the disposal of controls? Does anyone have any ideas on where to go from this?
Thanks in advance.