Memory Leak

M

Manoj Misran

After loosing all my hairs, I have finally come to a conclusion that
..NET is not made for 24/7 kind of business application because of
nasty memory leak and GC problems.

I developed a business application that is used for loading trucks in
a food processing plant. If this application stops, the entire loading
process comes to dead halt. I am using MDI with Menus and various Menu
Items and enabling/disabling Menu Items based upon user security. The
only Menu is on the Parent Form. There are no menus on any of the
child form. Now every time one user finish loading his truck and
logout the application holds some memory. It does not release complete
memory. The one and the only thing that I am doing in the logout
process is, Disabling all the Menu Items and show the login screen.

foreach(MenuItem M in mainMenu)
{
foreach(MenuItem N in mainMenu)
{
N.enabled = false;
}
M.enabled = false
}
Form loginForm = new LoginForm();
loginForm.ShowDialog();
loginForm.Dispose();
loginForm=null;

And in the login process, I am just enabling required MenuItems
depending upon user's security settings.

Now the Problem:
The application works perfactly fine for about 3-4 hours. But
gradually it runs out of memory and stops. User has to restart from
scratch. If he is in the middle of a transaction, he has to void the
entire transaction and regenerate the loading ticket.

Now the research part and why I lost all my hairs:

I baught a full copy of Memory Profiler just for this purpose. Did a
thorough and microscopic scan of all the objects generations and
disposals. Finally stuck at Menu Items. Just by enabling and disabling
MenuItems, the application holds Memory. It shows some
Hashtable.Bucket[] which has a reference to Menu Items. Nobody from
Microsoft talks about this thing.

I am so frustrated with the approach that Microsoft has taken with
this issue that I am partly deciding to moving away from .NET. I like
the overall ease of development in .NET but that doesn't help if I can
not make mission criticle applications like this.

Microsoft, pleeeeeeeeease understand that Menu and MenuItems are
integral requirement of every business application. I can possibly
find a workaround by totally removing all the menus and rewrite the
whole thing with my own menu system but that's not what I want. Had it
been a problem related to any other rarly used data structure, you can
hold on to it until the next release of framework but you can not do
the same for Menuitems.

I don't know what to do now. My management and the truck drivers are
loosing patience. Can someone help ...........

Microsoft, its a do or die situation for me. I have to take a decision
to be with .NET or forget it. Please do something...

Manoj Misran
(e-mail address removed)
 
J

Jesus Gandara

I'm in the same situation as you are. I am trying to upgrade an app from
VB6 to c# and it runs pretty slow in one of our sites, but it runs fine
in my computer, slow but fine.

Here is a suggestion to your problem:
Lets say you have your main MDI parent form with the menu, I assume they
have to login and log out several times.

You can declare the login form as part of the main form, and hide/show
it when its required. Also when the login screen is shown, make the main
firm invisible, so you don't have to disable all menus.

You can show the login using ShowDialog and wait for the response
ResponseDialog.OK if the login was successfull or ResponseDialog.Cancel
if not.

hope this can give you another options and live with the bug, or at
least avoid it
 
M

Manoj Misran

Thanks for the Reply Jesus,

In my application I have to enable or disable menu items based upon the
security profile of the logged-in user and its role. So its different
for different type of users. In this case, making the form invisible
will not help.

Manj Misran
 
J

Joe White

Since the problem is the main menu, why not try destroying and
re-creating the main menu each time you switch users?

If your menu design doesn't change often you could just copy the
relevant code out if InitializeComponent() into a separate procedure
that you call when you want to re-create the menu. You'd have to
re-copy the code whenever you changed the menu using the visual menu
designer, but it might be an OK workaround until MS fixes the bug.

BTW, are you actually calling Dispose() on the menu items when you don't
need them anymore? Or are you just removing them from the menu?


Manoj said:
After loosing all my hairs, I have finally come to a conclusion that
..NET is not made for 24/7 kind of business application because of
nasty memory leak and GC problems.

I developed a business application that is used for loading trucks in
a food processing plant. If this application stops, the entire loading
process comes to dead halt. I am using MDI with Menus and various Menu
Items and enabling/disabling Menu Items based upon user security. The
only Menu is on the Parent Form. There are no menus on any of the
child form. Now every time one user finish loading his truck and
logout the application holds some memory. It does not release complete
memory. The one and the only thing that I am doing in the logout
process is, Disabling all the Menu Items and show the login screen.

foreach(MenuItem M in mainMenu)
{
foreach(MenuItem N in mainMenu)
{
N.enabled = false;
}
M.enabled = false
}
Form loginForm = new LoginForm();
loginForm.ShowDialog();
loginForm.Dispose();
loginForm=null;

And in the login process, I am just enabling required MenuItems
depending upon user's security settings.

Now the Problem:
The application works perfactly fine for about 3-4 hours. But
gradually it runs out of memory and stops. User has to restart from
scratch. If he is in the middle of a transaction, he has to void the
entire transaction and regenerate the loading ticket.

Now the research part and why I lost all my hairs:

I baught a full copy of Memory Profiler just for this purpose. Did a
thorough and microscopic scan of all the objects generations and
disposals. Finally stuck at Menu Items. Just by enabling and disabling
MenuItems, the application holds Memory. It shows some
Hashtable.Bucket[] which has a reference to Menu Items. Nobody from
Microsoft talks about this thing.

I am so frustrated with the approach that Microsoft has taken with
this issue that I am partly deciding to moving away from .NET. I like
the overall ease of development in .NET but that doesn't help if I can
not make mission criticle applications like this.

Microsoft, pleeeeeeeeease understand that Menu and MenuItems are
integral requirement of every business application. I can possibly
find a workaround by totally removing all the menus and rewrite the
whole thing with my own menu system but that's not what I want. Had it
been a problem related to any other rarly used data structure, you can
hold on to it until the next release of framework but you can not do
the same for Menuitems.

I don't know what to do now. My management and the truck drivers are
loosing patience. Can someone help ...........

Microsoft, its a do or die situation for me. I have to take a decision
to be with .NET or forget it. Please do something...

Manoj Misran
(e-mail address removed)
 
M

Manoj Misran

I did the same Joe, and I am sorry, it did the same thing again. By
changing the sequence of disposing menuitems, I can minimize it to
some extent but could not make it to zero. I can make it to zero only
if I have one submenu in the main menu. But if I have two or more
submenus, I can't remove it from memory completely. I tried all the
possibilities.
I am posing my code here whicj I extracted from the main application.
Try different combination of creating Main Menu and sub menus by
clicking buttons on the form. See if you can make any sense out of it.
i am frustrated now...


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();
}
}
}
 
J

JerryK

If you are using merged menues with MDI then this is a known issue. MS has
acknowldged this.

Check previous messages for instructions on writing your own menu manager.

Manoj Misran said:
After loosing all my hairs, I have finally come to a conclusion that
.NET is not made for 24/7 kind of business application because of
nasty memory leak and GC problems.

I developed a business application that is used for loading trucks in
a food processing plant. If this application stops, the entire loading
process comes to dead halt. I am using MDI with Menus and various Menu
Items and enabling/disabling Menu Items based upon user security. The
only Menu is on the Parent Form. There are no menus on any of the
child form. Now every time one user finish loading his truck and
logout the application holds some memory. It does not release complete
memory. The one and the only thing that I am doing in the logout
process is, Disabling all the Menu Items and show the login screen.

foreach(MenuItem M in mainMenu)
{
foreach(MenuItem N in mainMenu)
{
N.enabled = false;
}
M.enabled = false
}
Form loginForm = new LoginForm();
loginForm.ShowDialog();
loginForm.Dispose();
loginForm=null;

And in the login process, I am just enabling required MenuItems
depending upon user's security settings.

Now the Problem:
The application works perfactly fine for about 3-4 hours. But
gradually it runs out of memory and stops. User has to restart from
scratch. If he is in the middle of a transaction, he has to void the
entire transaction and regenerate the loading ticket.

Now the research part and why I lost all my hairs:

I baught a full copy of Memory Profiler just for this purpose. Did a
thorough and microscopic scan of all the objects generations and
disposals. Finally stuck at Menu Items. Just by enabling and disabling
MenuItems, the application holds Memory. It shows some
Hashtable.Bucket[] which has a reference to Menu Items. Nobody from
Microsoft talks about this thing.

I am so frustrated with the approach that Microsoft has taken with
this issue that I am partly deciding to moving away from .NET. I like
the overall ease of development in .NET but that doesn't help if I can
not make mission criticle applications like this.

Microsoft, pleeeeeeeeease understand that Menu and MenuItems are
integral requirement of every business application. I can possibly
find a workaround by totally removing all the menus and rewrite the
whole thing with my own menu system but that's not what I want. Had it
been a problem related to any other rarly used data structure, you can
hold on to it until the next release of framework but you can not do
the same for Menuitems.

I don't know what to do now. My management and the truck drivers are
loosing patience. Can someone help ...........

Microsoft, its a do or die situation for me. I have to take a decision
to be with .NET or forget it. Please do something...

Manoj Misran
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top