12

I have a Windows Form Application in which clicking certain buttons create objects from a 2nd Form. On closing this 2nd Form by the user, the memory used by this form is not released (according to Task Manager).

I tried using this.dispose() on exit button, this.close(), form2 = null in the main code, and tried clearing all controls from this form by code before disposing. None of this has worked and every time the user clicks the button, the memory usage by the application increases and memory used by the previous instance is not released.

What shall I use to solve this problem?

Keplah
  • 954
  • 2
  • 13
  • 26
EgyEast
  • 1,542
  • 6
  • 28
  • 44
  • 2
    Are you perhaps looking for a way to free memory allocated by a child object of the form? A simple form class has such low memory consumption that I can't imagine anyone making a forum posting regarding this... – Adrian Grigore May 30 '10 at 22:51

4 Answers4

20

Calling Dispose will not clean up the memory used by an object. Dispose is meant to be used to run user defined code that releases resources that are not automatically released - like file handles, network handles, database connections etc.

The likely culprit is probably the second form attaching events to objects that are outside it (perhaps the first form?) and never unattaching them.

If you have any events in the second form, unattach them in your OnClose override - that will make the second form eligible for garbage collection.

Note, .NET garbage collector is quite unpredictable and it might create a few instances of an object before cleaning up all the older instances that were eligible for collection. A way to know for sure (without resorting to memory profilers) is to put a breakpoint in the finalizer:

public class MyForm : Form {
  ~MyForm() {
    //breakpoint here
  }
}

If the finalizer gets called then this class is OK, if not, you still have a leak. You can also give GC a "kick" - but only for troubleshooting purposes - do not leave this code in production - by initiating GC:

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

Put the above code somewhere that runs after you close and dispose the second form. You should hit the breakpoint in MyForm finalizer.

Igor Zevaka
  • 74,528
  • 26
  • 112
  • 128
  • I followed these suggestions, but even after putting in the GC code, my Form finalize function is not hitting its break point. I have a bad memory leak it looks like. I am using OpenTK in a separate Form with OpenGL, maybe that is it? – theJerm Nov 13 '13 at 04:54
  • That's why I like C++ more. – Baso May 12 '15 at 15:08
3

Dispose isn't for releasing memory - the common language runtime's garbage collector takes care of that. Dispose is for releasing other (non-memory) scarce resources like database connections and file handles.

Generally speaking, you don't need to worry about memory consumption in your .NET applications because the framework does it for you. If you need finer control over memory consumption, you should be developing in a language that provides that control, like C++.

Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
0

Don't call Dispose() method, call ->>>>> Dispose(true) instead and you will be surprised a lot. It actually freeing memory, you may observe an effect in the task manager.

Wallstrider
  • 856
  • 1
  • 7
  • 22
  • 1
    `Dispose()` calls `Dispose(true)`. That's a protected method; you should not call that. – SLaks Aug 22 '16 at 18:23
  • Yes it's protected, not private. So there is no reason to not call it. Dispose(bool disposing) executes in two distinct scenarios. If disposing equals true, the method has been called directly or indirectly by a user's code. Managed and unmanaged resources can be disposed. If disposing equals false, the method has been called by the runtime from inside the finalizer and you should not reference other objects. Only unmanaged resources can be disposed. © MSDN – Wallstrider Aug 23 '16 at 14:44
  • `Dispose()` calls `Dispose(true)`. The inner method is an implementation detail and should not be called directly. – SLaks Aug 23 '16 at 15:09
  • This is not a reason or an official restriction. Dispose() calls: Dispose(true); GC.SuppressFinalize(this); GC.SuppressFinalize(this); is a problem here so when you call just Dispose(true) nothing bad will happen. So if it would be restricted it probably would be an protected internal method. – Wallstrider Aug 23 '16 at 15:27
  • `GC.SuppressFinalize()` is not a problem; it's just a GC optimization. You need to understand how the dispose pattern works. – SLaks Aug 23 '16 at 16:00
  • I know how it works. In case of this topic GC.SuppressFinalize() isn't necessary, so my solution works. If it doesn't work please let me know. – Wallstrider Aug 24 '16 at 15:51
  • No, SuppressFinalize is still necessary. Once you've called `Dispose()`, you don't need to pollute the finalizer queue. – SLaks Aug 24 '16 at 17:25
  • The GC is a big mess itself. I would not spend much time on it. I'd better wrote a program on C++ then. There is still no best answer maybe you have one? :D – Wallstrider Aug 24 '16 at 18:04
0

Sounds like the memory is still being used because disposed object have not been reclaimed by the garbage collector. Try using the GC.Collect() static method to force a garbage collection. Watch out for performance issues as this normally halts your program until it has finished.

GC.Collect();
Jason
  • 3,736
  • 5
  • 33
  • 40