M
Manoj Misran
All the GURUs, Need you help pleeeeaaaaaaaaase.
I am having trouble keeping an application working for more than 3-4
hours. It is a business critical app and is suppose to work 24/7.
The app runs out of memory because of a memory leak. I did the
thorough reasearch and reached to a point where I am stuck. I have
created the following sample application extracted from my original
application and it reproduces the memory leak.
Here is the code, followed by my brief explaination about the code and
my findings:
/**------------------------------------------------------------**/
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Monitor
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
private System.Windows.Forms.MenuItem menuItemTransaction;
private System.Windows.Forms.MenuItem menuItemLoadTruck;
private System.Windows.Forms.MenuItem menuItemFile;
private System.Windows.Forms.MenuItem menuItemPrinterSetup;
private System.Windows.Forms.MenuItem menuItemLogout;
private System.Windows.Forms.MenuItem menuItemUpgrade;
private System.Windows.Forms.MenuItem menuItemPhInventory;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (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.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(48, 112);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(88, 23);
this.button1.TabIndex = 0;
this.button1.Text = "AddFile";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(168, 112);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(88, 23);
this.button2.TabIndex = 1;
this.button2.Text = "RemoveFile";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button3
//
this.button3.Location = new System.Drawing.Point(48, 64);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(88, 23);
this.button3.TabIndex = 2;
this.button3.Text = "AddMain";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(168, 64);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(88, 23);
this.button4.TabIndex = 3;
this.button4.Text = "RemoveMain";
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// button5
//
this.button5.Location = new System.Drawing.Point(48, 160);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(88, 23);
this.button5.TabIndex = 4;
this.button5.Text = "AddTran";
this.button5.Click += new System.EventHandler(this.button5_Click);
//
// button6
//
this.button6.Location = new System.Drawing.Point(168, 160);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(88, 23);
this.button6.TabIndex = 5;
this.button6.Text = "RemoveTran";
this.button6.Click += new System.EventHandler(this.button6_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.button6);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void AddMainMenu()
{
this.Menu = new System.Windows.Forms.MainMenu();
}
private void RemoveMainMenu()
{
this.Menu.MenuItems.Clear();
this.Menu.Dispose();
this.Menu = null;
}
private void AddFileMenu()
{
this.menuItemFile = new System.Windows.Forms.MenuItem();
this.menuItemPrinterSetup = new System.Windows.Forms.MenuItem();
this.menuItemUpgrade = new System.Windows.Forms.MenuItem();
this.menuItemLogout = new System.Windows.Forms.MenuItem();
this.menuItemFile.Index = 0;
this.menuItemFile.Text = "&File";
this.menuItemPrinterSetup.Index = 0;
this.menuItemPrinterSetup.Text = "&Printer Setup";
this.menuItemUpgrade.Index = 2;
this.menuItemUpgrade.Text = "Upgrade";
this.menuItemLogout.Index = 3;
this.menuItemLogout.Shortcut = System.Windows.Forms.Shortcut.CtrlL;
this.menuItemLogout.Text = "&Logout ";
this.menuItemUpgrade.Click += new
System.EventHandler(this.menuItemUpgrade_Click);
this.menuItemLogout.Click += new
System.EventHandler(this.menuItemLogout_Click);
this.menuItemFile.MenuItems.Add(this.menuItemPrinterSetup);
this.menuItemFile.MenuItems.Add(this.menuItemLogout);
this.menuItemFile.MenuItems.Add(this.menuItemUpgrade);
this.Menu.MenuItems.Add(this.menuItemFile);
}
private void RemoveFileMenu()
{
this.menuItemFile.MenuItems.Clear();
this.menuItemFile.Dispose();
this.menuItemFile = null;
this.menuItemUpgrade.Click -= new
System.EventHandler(this.menuItemUpgrade_Click);
this.menuItemLogout.Click -= new
System.EventHandler(this.menuItemLogout_Click);
this.menuItemPrinterSetup.Dispose();
this.menuItemPrinterSetup = null;
this.menuItemUpgrade.Dispose();
this.menuItemUpgrade = null;
this.menuItemLogout.Dispose();
this.menuItemLogout = null;
}
private void AddTransactionMenu()
{
this.menuItemTransaction = new System.Windows.Forms.MenuItem();
this.menuItemLoadTruck = new System.Windows.Forms.MenuItem();
this.menuItemPhInventory = new System.Windows.Forms.MenuItem();
this.menuItemTransaction.Index = 1;
this.menuItemTransaction.Text = "&Transactions";
this.menuItemLoadTruck.Index = 0;
this.menuItemLoadTruck.Shortcut = System.Windows.Forms.Shortcut.F6;
this.menuItemLoadTruck.Text = "&Load Truck ";
this.menuItemPhInventory.Index = 1;
this.menuItemPhInventory.Text = "&Physical Inventory";
this.menuItemLoadTruck.Click += new
System.EventHandler(this.menuItemLoadTruck_Click);
this.menuItemPhInventory.Click += new
System.EventHandler(this.menuItemPhInventory_Click);
this.menuItemTransaction.MenuItems.Add(this.menuItemLoadTruck);
this.menuItemTransaction.MenuItems.Add(this.menuItemPhInventory);
this.Menu.MenuItems.Add(this.menuItemTransaction);
}
private void RemoveTransactionMenu()
{
this.menuItemTransaction.MenuItems.Clear();
this.menuItemTransaction.Dispose();
this.menuItemTransaction = null;
this.menuItemLoadTruck.Click -= new
System.EventHandler(this.menuItemLoadTruck_Click);
this.menuItemPhInventory.Click -= new
System.EventHandler(this.menuItemPhInventory_Click);
this.menuItemLoadTruck.Dispose();
this.menuItemLoadTruck = null;
this.menuItemPhInventory.Dispose();
this.menuItemPhInventory = null;
}
private void menuItemLoadTruck_Click(object sender, System.EventArgs
e)
{
}
private void menuItemLogout_Click(object sender, System.EventArgs e)
{
}
private void menuItemUpgrade_Click(object sender, System.EventArgs
e)
{
}
private void menuItemPhInventory_Click(object sender,
System.EventArgs e)
{
}
private void button1_Click(object sender, System.EventArgs e)
{
AddFileMenu();
}
private void button2_Click(object sender, System.EventArgs e)
{
RemoveFileMenu();
}
private void button3_Click(object sender, System.EventArgs e)
{
AddMainMenu();
}
private void button4_Click(object sender, System.EventArgs e)
{
RemoveMainMenu();
}
private void button5_Click(object sender, System.EventArgs e)
{
AddTransactionMenu();
}
private void button6_Click(object sender, System.EventArgs e)
{
RemoveTransactionMenu();
}
}
}
/**-----------------------------------------**/
The above sample app. has six buttons to create and destroy all the
menu items. If I create the full menu, its structure will be like
this:
Main Menu
- File
- Printer Setup
- Logout
- Upgrade
- Transaction
- Load Truck
- Physical Inventory
Now, if you run this sample application, and click in this sequence
"AddMain" - "AddFile" - "RemoveFile" - "RemoveMain" all the menu items
will not be destroyed and you will have a reference in the memory and
it will not be collected by GC.
BUT, if you change the sequence to "AddMain" - "AddFile" -
"RemoveMain" - "RemoveFile", now it will remove everything from memory
and its clean. I don't understand a bit why this behaviour.
Now the LAST and the most important:
Earlier I added only one submenu and it gets removed completely if I
use the second click-sequence, BUT if I add two submenus, there is no
way I can get rid of all of them in any way. By doing different
permutation and combination the most optimum that I found was the
following sequence:
"AddMain" - "AddFile" - "AddTransaction" - "RemoveMain" - "RemoveFile"
- "RemoveTransaction". Still I have three menu items in the memory and
this accumulates everytime I create or destroy the menu.
I don't know what to do now. Please see if it makes any sense to you.
You can directly write to me at (e-mail address removed)
Thanks in advance
-Manoj Misran
I am having trouble keeping an application working for more than 3-4
hours. It is a business critical app and is suppose to work 24/7.
The app runs out of memory because of a memory leak. I did the
thorough reasearch and reached to a point where I am stuck. I have
created the following sample application extracted from my original
application and it reproduces the memory leak.
Here is the code, followed by my brief explaination about the code and
my findings:
/**------------------------------------------------------------**/
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Monitor
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.ComponentModel.Container components = null;
private System.Windows.Forms.MenuItem menuItemTransaction;
private System.Windows.Forms.MenuItem menuItemLoadTruck;
private System.Windows.Forms.MenuItem menuItemFile;
private System.Windows.Forms.MenuItem menuItemPrinterSetup;
private System.Windows.Forms.MenuItem menuItemLogout;
private System.Windows.Forms.MenuItem menuItemUpgrade;
private System.Windows.Forms.MenuItem menuItemPhInventory;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
private System.Windows.Forms.Button button5;
private System.Windows.Forms.Button button6;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (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.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.button5 = new System.Windows.Forms.Button();
this.button6 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(48, 112);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(88, 23);
this.button1.TabIndex = 0;
this.button1.Text = "AddFile";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// button2
//
this.button2.Location = new System.Drawing.Point(168, 112);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(88, 23);
this.button2.TabIndex = 1;
this.button2.Text = "RemoveFile";
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// button3
//
this.button3.Location = new System.Drawing.Point(48, 64);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(88, 23);
this.button3.TabIndex = 2;
this.button3.Text = "AddMain";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(168, 64);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(88, 23);
this.button4.TabIndex = 3;
this.button4.Text = "RemoveMain";
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// button5
//
this.button5.Location = new System.Drawing.Point(48, 160);
this.button5.Name = "button5";
this.button5.Size = new System.Drawing.Size(88, 23);
this.button5.TabIndex = 4;
this.button5.Text = "AddTran";
this.button5.Click += new System.EventHandler(this.button5_Click);
//
// button6
//
this.button6.Location = new System.Drawing.Point(168, 160);
this.button6.Name = "button6";
this.button6.Size = new System.Drawing.Size(88, 23);
this.button6.TabIndex = 5;
this.button6.Text = "RemoveTran";
this.button6.Click += new System.EventHandler(this.button6_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.button6);
this.Controls.Add(this.button5);
this.Controls.Add(this.button4);
this.Controls.Add(this.button3);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void AddMainMenu()
{
this.Menu = new System.Windows.Forms.MainMenu();
}
private void RemoveMainMenu()
{
this.Menu.MenuItems.Clear();
this.Menu.Dispose();
this.Menu = null;
}
private void AddFileMenu()
{
this.menuItemFile = new System.Windows.Forms.MenuItem();
this.menuItemPrinterSetup = new System.Windows.Forms.MenuItem();
this.menuItemUpgrade = new System.Windows.Forms.MenuItem();
this.menuItemLogout = new System.Windows.Forms.MenuItem();
this.menuItemFile.Index = 0;
this.menuItemFile.Text = "&File";
this.menuItemPrinterSetup.Index = 0;
this.menuItemPrinterSetup.Text = "&Printer Setup";
this.menuItemUpgrade.Index = 2;
this.menuItemUpgrade.Text = "Upgrade";
this.menuItemLogout.Index = 3;
this.menuItemLogout.Shortcut = System.Windows.Forms.Shortcut.CtrlL;
this.menuItemLogout.Text = "&Logout ";
this.menuItemUpgrade.Click += new
System.EventHandler(this.menuItemUpgrade_Click);
this.menuItemLogout.Click += new
System.EventHandler(this.menuItemLogout_Click);
this.menuItemFile.MenuItems.Add(this.menuItemPrinterSetup);
this.menuItemFile.MenuItems.Add(this.menuItemLogout);
this.menuItemFile.MenuItems.Add(this.menuItemUpgrade);
this.Menu.MenuItems.Add(this.menuItemFile);
}
private void RemoveFileMenu()
{
this.menuItemFile.MenuItems.Clear();
this.menuItemFile.Dispose();
this.menuItemFile = null;
this.menuItemUpgrade.Click -= new
System.EventHandler(this.menuItemUpgrade_Click);
this.menuItemLogout.Click -= new
System.EventHandler(this.menuItemLogout_Click);
this.menuItemPrinterSetup.Dispose();
this.menuItemPrinterSetup = null;
this.menuItemUpgrade.Dispose();
this.menuItemUpgrade = null;
this.menuItemLogout.Dispose();
this.menuItemLogout = null;
}
private void AddTransactionMenu()
{
this.menuItemTransaction = new System.Windows.Forms.MenuItem();
this.menuItemLoadTruck = new System.Windows.Forms.MenuItem();
this.menuItemPhInventory = new System.Windows.Forms.MenuItem();
this.menuItemTransaction.Index = 1;
this.menuItemTransaction.Text = "&Transactions";
this.menuItemLoadTruck.Index = 0;
this.menuItemLoadTruck.Shortcut = System.Windows.Forms.Shortcut.F6;
this.menuItemLoadTruck.Text = "&Load Truck ";
this.menuItemPhInventory.Index = 1;
this.menuItemPhInventory.Text = "&Physical Inventory";
this.menuItemLoadTruck.Click += new
System.EventHandler(this.menuItemLoadTruck_Click);
this.menuItemPhInventory.Click += new
System.EventHandler(this.menuItemPhInventory_Click);
this.menuItemTransaction.MenuItems.Add(this.menuItemLoadTruck);
this.menuItemTransaction.MenuItems.Add(this.menuItemPhInventory);
this.Menu.MenuItems.Add(this.menuItemTransaction);
}
private void RemoveTransactionMenu()
{
this.menuItemTransaction.MenuItems.Clear();
this.menuItemTransaction.Dispose();
this.menuItemTransaction = null;
this.menuItemLoadTruck.Click -= new
System.EventHandler(this.menuItemLoadTruck_Click);
this.menuItemPhInventory.Click -= new
System.EventHandler(this.menuItemPhInventory_Click);
this.menuItemLoadTruck.Dispose();
this.menuItemLoadTruck = null;
this.menuItemPhInventory.Dispose();
this.menuItemPhInventory = null;
}
private void menuItemLoadTruck_Click(object sender, System.EventArgs
e)
{
}
private void menuItemLogout_Click(object sender, System.EventArgs e)
{
}
private void menuItemUpgrade_Click(object sender, System.EventArgs
e)
{
}
private void menuItemPhInventory_Click(object sender,
System.EventArgs e)
{
}
private void button1_Click(object sender, System.EventArgs e)
{
AddFileMenu();
}
private void button2_Click(object sender, System.EventArgs e)
{
RemoveFileMenu();
}
private void button3_Click(object sender, System.EventArgs e)
{
AddMainMenu();
}
private void button4_Click(object sender, System.EventArgs e)
{
RemoveMainMenu();
}
private void button5_Click(object sender, System.EventArgs e)
{
AddTransactionMenu();
}
private void button6_Click(object sender, System.EventArgs e)
{
RemoveTransactionMenu();
}
}
}
/**-----------------------------------------**/
The above sample app. has six buttons to create and destroy all the
menu items. If I create the full menu, its structure will be like
this:
Main Menu
- File
- Printer Setup
- Logout
- Upgrade
- Transaction
- Load Truck
- Physical Inventory
Now, if you run this sample application, and click in this sequence
"AddMain" - "AddFile" - "RemoveFile" - "RemoveMain" all the menu items
will not be destroyed and you will have a reference in the memory and
it will not be collected by GC.
BUT, if you change the sequence to "AddMain" - "AddFile" -
"RemoveMain" - "RemoveFile", now it will remove everything from memory
and its clean. I don't understand a bit why this behaviour.
Now the LAST and the most important:
Earlier I added only one submenu and it gets removed completely if I
use the second click-sequence, BUT if I add two submenus, there is no
way I can get rid of all of them in any way. By doing different
permutation and combination the most optimum that I found was the
following sequence:
"AddMain" - "AddFile" - "AddTransaction" - "RemoveMain" - "RemoveFile"
- "RemoveTransaction". Still I have three menu items in the memory and
this accumulates everytime I create or destroy the menu.
I don't know what to do now. Please see if it makes any sense to you.
You can directly write to me at (e-mail address removed)
Thanks in advance
-Manoj Misran