0

I am programming a inventory system in Windows Forms using C# and I designed it with a admin dashboard looking. I am using MDI and I load the products by clicking the products button.

enter image description here

When loading the child form everything works ok: enter image description here

But when I load the products again and again I noticed that in Windows Task Manager the program is consuming too much memory every time I load the products or click products button. The memory consumption is being very aggressive.

This is my code:

loading the child form from parent:

  public partial class Layout2 : BaseContext
{
    public Layout2()
    {
        InitializeComponent();
    }
    
    //loads the products form 
    private void ventas_boton_Click(object sender, EventArgs e)
    {
        var frm = new Inventario();
        frm.TopLevel = false;
        frm.FormBorderStyle = FormBorderStyle.None;
        panel3.Controls.Add(frm);
        frm.WindowState = FormWindowState.Maximized;
        frm.Visible = true;
    }

}

child form stuff

public partial class Inventario : BaseContext
{

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        CargarLista();

    }

    public virtual void CargarLista()
    {
        var productos = _inventarioRepository.GetList();
        ListaProductos.DataSource = productos;

    }


}

Base Context

public class BaseContext: Form
{
    // contexto base, todos los forms deben heredar esta clase por orden.

    private bool _disposed = false;
    protected Context _context { get; set; }

    public BaseContext()
    {
        _context = new Context();
    }

    protected override void Dispose(bool disposing)
    {
        if (_disposed) return;
        if (disposing) _context.Dispose();
        _disposed = true;
        base.Dispose(disposing);
    }
}

I think var frm = new Inventario(); is causing the problem because it is creating new object every time I click the button to show the form.

My issue is simple but I am new at Windows Forms, How do I solve this memory consumption every time I open or update the products form?

EthernalHusky
  • 485
  • 7
  • 19
  • 2
    I'm not a WinForm programmer, but I think you're on the right path. You are creating a new object and adding it to panel3 over and over. You are never removing what you previously added to panel3. Take a look at this answer to see if it helps: https://stackoverflow.com/a/14423245/130387 – Tommy Aug 01 '20 at 21:56
  • 1
    So, every time when you click a button it opens a new child form and you never close child forms. Am I correct? – default locale Aug 01 '20 at 21:57
  • Thats correct, since they're child forms they must be sticked in the *panel* and they must not have close buttons. – EthernalHusky Aug 01 '20 at 21:59
  • 1
    Naturally, child forms are going to keep their memory. You need to figure out the plan to close previously opened child forms at some point. Do you want to close them automatically when the new `Inventario` is open? – default locale Aug 01 '20 at 22:02
  • Yes, that would be a good idea to close the previous child form when button is clicked. I think another good idea would be that when I click products button it will not load the form again because it is already opened and this will avoid creating new form instances. I think the second option would he good. – EthernalHusky Aug 01 '20 at 22:06
  • How much is *"too much memory"*? Managed applications continually increase their memory footprint until a garbage collection takes place. Try adding a temporary button on the form that executed `GC.Collect(); GC.WaitForPendingFinalizers();` and see if the memory growth subsides. Task Manager is a poor way to examine managed memory usage. Use the managed memory counters in Performance Manager. – Flydog57 Aug 01 '20 at 22:26

1 Answers1

2

I think another good idea would be that when I click products button it will not load the form because it is already opened. I think the second option would he good.

You can check if the product's form is already open using panel3.Controls. Something like this should work:

//loads the products form 
private void ventas_boton_Click(object sender, EventArgs e)
{
    if (panel3.Controls.OfType<Inventario>().Any()) return;
    var frm = new Inventario();
    ...

UPDATE: You can also create a generic method, that you can use with different types of forms:

private  void AddForm<T>(Func<T> formCreator) where T: Form
{
    var form = panel3.Controls.OfType<T>().FirstOrDefault();
    if (form != null)
    {
        //if the form of a given type already exists bring it to front
        form.BringToFront();
        return;
    }
    form = formCreator();
    form.TopLevel = false;
    form.FormBorderStyle = FormBorderStyle.None;
    form.WindowState = FormWindowState.Maximized;
    form.Visible = true;
    panel3.Controls.Add(form);
}

Then you can use it like this:

AddForm(() => new Inventario());
AddForm(() => new ClientForm());
default locale
  • 13,035
  • 13
  • 56
  • 62