0

I have a class, where, based on a certain event, I initialize a new form based dialog and initialize it. This form based dialog has other controls inside it.

When the dialog is closed, I clear and dispose off all the controls which are created in the form. Unfortunately, it seems that something is not getting disposed, or remaining in memory even after the removal.

Form pump

class someClass
{
    System.Timers.Timer someTimer;
    public void CallToChildThread(Object stateInfo)
    {
       // check some event
      // if true, fire event
    }
    someClass()
    {
          someTimer= new System.Threading.Timer(CallToChildThread,
                                   autoEvent, 1000, 250);
            _show += new EventHandler(eventCheck);
    }
    void eventCheck()
    {
        formClass formClassObject = new formClass(); //create form
        formClassObject.someFunction(); // has some other function and does a showDialog on self
        formClassObject.Dispose();
        formClassObject = null;
    }
}

Inside the formClass object, upon getting the FormClosed event, I dispose off all the controls and controls within the controls within the object, but there is still a noticable memory leak.

Form class

public partial class formClass
{
    //Initialize a bunch of managed  resources to null
    someOtherForm form2;
    someOtherForm form3;
    //connect some events on child forms to buttons on this form object
    this.form2.cancelButtonClicked += someFunction;
    this.form3.cancelButtonClicked += someFunction;
    // Form closed Event
    private void formClass_FormClosed(object sender, FormClosedEventArgs e)
    {
        //set form2 and form3 visibility to false
        // clear AND dispose all controls of form2
        // clear AND dispose all controls of form3
        //set form2 and form3 to null
        // clear AND dispose off all controls of formClass 
        // Dispose this (formClass) object
     }
}

Is there a possible issue with the way I have initialized the form objects? Are those not getting disposed?

user1173240
  • 1,455
  • 2
  • 23
  • 50
  • 3
    Why do you think that there is a memory leak? Note that the garbage collection decides by itself _when_ to actually free the memory. This happens not necessarily immediatly, but can eventually be done when gc notices that there is no more enough memory to fulfill the next allocation request. btw: if you dispose the form, it will dispose all its controls itself, no need to do this manually. – René Vogt Feb 01 '17 at 16:33
  • What behavior leads you to believe that there is a memory leak? – tonythewest Feb 01 '17 at 16:33
  • 1
    Try to dispose the timer as well as the form object? – Neil Busse Feb 01 '17 at 16:34
  • 1
    You are not disposing [`someTimer`](https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx). Since it's not in the form, if you create instances of `someClass` (it's not clear how many of them you have) they will all stay and even worse continue firing events. – Sinatr Feb 01 '17 at 16:36
  • Memory leaks can be hard to diagnose in C#, as the GC is nondeterministic. Calling `Dispose()` doesn't necessarily release the space the object took from memory. You can try `GC.Collect`, but that will halt all threads no matter which thread you run it on, and it may still not completely clean things up. Are you getting `OutOfMemoryExceptions`? – CDove Feb 01 '17 at 16:53
  • Like everyone said, someTimer which is a Timer object which implements IDisposable. See https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx – Andez Feb 01 '17 at 17:23
  • I have only a single instance of someClass. So there is only a single timer object. That should not be the case of the leak. I think there is a leak, because each time I fire an event which creates a new form and initializes controls, memory increases noticeably. Separately, the User Objects counter in Task Manage for the application goes up. If I open 10 forms, memory increases by quite a bit, so do the User Objects, but neither comes down even if I close all the forms, no matter how long I leave the application running. The User Objects count dips by a bit but remains high. – user1173240 Feb 01 '17 at 17:50
  • 1
    Where do you see that _memory increases noticeably_? Are you using a memory profiler? – Chris Dunaway Feb 01 '17 at 19:54
  • @Chris No, I see it in task manager, and also the User Objects count inside task manager. Both jump relatively significantly upon each call for the form, and it does not go down even after a long time after form closure. I know task manager isn't the best, but process memory + increasing user object count not decreasing at all after a long time is indicative probably. This leads me to think memory is leaking because some object is not being claimed back. – user1173240 Feb 02 '17 at 04:15

2 Answers2

1

Please see here: Memory Leaks in Winforms application

Try to remove the event handler (_show) prior to disposing to truly have the child forms memory disposed of.

Community
  • 1
  • 1
Ryan C
  • 572
  • 5
  • 18
  • Permit me to ask what may be a silly question... How does the event, _show, affect an object of formClass? It's just an event in someClass (which is not a form), which is signalled when a condition is met within the timer. Also, if I dispose off this event, _show, then what will the timer signal later on? – user1173240 Feb 01 '17 at 18:39
  • @user1173240 I'm not sure as I don't see your `form.someFunction` method inside of your response, but to properly detect the issue, I would need to see your entire `formClass` object. Disposing or closing the form only gets rid of the UI elements. If you have any variables, objects, eventhandlers, etc...in your `formClass`, you need to have the `FormClosed` event of the form call `.Dispose()` on all objects in itself. That's my best guess without seeing all of the code for myself. – Ryan C Feb 01 '17 at 20:52
  • I've added some code, which describes essentially what I am doing in the formClass formClosed event. – user1173240 Feb 02 '17 at 07:56
0

You are not removing the event handler and this could be a source of leak. Probably you should make someClass disposable and remove the handler in Dispose method.

How do you verify that there is a leak ? The garbage collector may run with a delay, giving the feeling that memory is not collected. You can explicitly call the gb after each form disposal and see what happens:

formClassObject.Dispose();

GC.Collect();  
GC.WaitForPendingFinalizers();  
GC.Collect();  
GC.WaitForPendingFinalizers();

Some other hints:

The forms you create could throw exceptions and not disposed properly. Since you create modal dialogs (calling ShowDialog) you should use the using pattern:

using (formClass formClassObject = new formClass())
{
   formClassObject.someFunction();
}

You can troubleshoot the leak using .NET profilers.

See this post for alternatives:

What Are Some Good .NET Profilers?

Community
  • 1
  • 1
GeorgeT
  • 484
  • 3
  • 5
  • think there is a leak, because each time I fire an event which creates a new form and initializes controls, memory increases noticeably. Separately, the User Objects counter in Task Manage for the application goes up. If I open 10 forms, memory increases by quite a bit, so do the User Objects, but neither comes down even if I close all the forms, no matter how long I leave the application running. The User Objects count dips by a bit but remains high. I thought it could be an issue with the data source for the UI, but all objects and controls are managed, and should go away with form closure – user1173240 Feb 01 '17 at 17:53
  • It makes sense. Possibly you could pin down the problem with a .NET profiler or by gradually lightening your form class doing minimal things (if possible). Usually it is the data source which is not properly disposed (as you already suspect), if big memory leak is detected. – GeorgeT Feb 01 '17 at 18:41