3

I have a main window in my project, and numerous other child widows inside the main.
I have noticed that. When I open the main window occupies 1500K of memory, when open one child window then adds in occupied memory 6000K.
When I open the second window doing the same. When I close the two child windows the occupied memory is not released.
So What I want is to release the occupied memory when ever I close child windows.
How I can do that?
Please advice me with some code example in vb.net if it is possible.
This problem often sawing in the computers on the Local NET not in my computer (developer computer which has the SQL server on it).

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
Lefteris Gkinis
  • 1,229
  • 6
  • 26
  • 63
  • 6000kB isn't very much these days! When you have a small application the overhead of common assemblies will be disproportionally high (lots of code you're not using). Also "occupied memory" is not a term for any of Windows memory statistics, without knowing what measure you are looking at it is hard to be specific (and all of the memory statistics need to be used carefully: there is no simple concept of memory with a virtual memory system that actively shares and purges pages). – Richard Mar 04 '11 at 09:39
  • See my updated answer more closer. Implement Idisposable interface where unmanaged resources are used and add the following code with some change in class and its constructor destructor name. And whereever you are closing child , call me.disposing(true). oping it will help –  Mar 04 '11 at 09:51

7 Answers7

13

Some of the other answers to this question contain a disappointing amount of misinformation, while others vastly over-complicate the issue. There are a lot of misconceptions surrounding garbage collection in .NET, and the theories being bandied about here are certainly not helping the problem.

First of all, profiling memory usage with Windows Task Manager is a huge mistake. You will get seriously invalid information, and attempting to modify your application according to this information is only going to make things worse, rather than better. If you suspect that you have performance problems (and it's very doubtful that the majority of applications actually will experience any), you need to invest in a proper memory profiler and use that instead.

Second, the whole point of garbage collection is that you don't have to worry about this kind of thing. And not only do you not have to worry about it, but you shouldn't worry about it, either. You should not be doing or attempting any type of manual memory management when writing applications targeting the .NET Framework. Resist the temptation to tinker with the internal workings of the garbage collector, and plant your fingers firmly in your ears when anyone tells you to call GC.Collect manually to force a garbage collection to occur. I suppose I shouldn't say never, but there is hardly ever a reason to do this. I'm far more likely to be suspect of code that manually invokes garbage collection than anything else.

Why shouldn't you manually invoke garbage collection? Well, beyond the obvious argument that it defeats the whole point of using a managed language in the first place, it's because garbage collection is an arduously slow and expensive process. You want it to run as rarely as possible in order to maintain peak performance. Fortunately, the programmers who implemented the garbage collection algorithms are much smarter and more experienced than either you or I: they designed it to run only when necessary, and no more often than that. You won't see an advantage of running it more often, but you will see a disadvantage. This is supposed to be completely opaque to you as the programmer.

The only exception is when you're working with unmanaged objects, which are not collected or managed by the garbage collector. You'll be able to recognize these objects because they all implement the IDisposable interface, which provides a Dispose method to release unmanaged resources. On objects that expose this method, you should call it as soon as you finish using the object. Or better yet, wrap the declaration and use of the object in a using statement, which will automatically handle disposing the object, no matter what happens (even if an exception is thrown in the code where you use the object, for example).

Of course, you will notice that several of the standard objects in the Windows Forms library implement the IDisposable method. The ubiquitous Form class, for example, provides a Dispose method. However, that does not necessarily mean that you are responsible for disposing of these objects manually. In general, you only need to explicitly call the Dispose method for objects that you explicitly create—easy to remember, right? The objects created automatically by the Framework are also automatically destroyed by the Framework. For example, the controls you place on a Form object at design-time are automatically disposed when their container form is disposed. And Form objects themselves are automatically disposed when they are closed. This is particularly relevant to the issue brought up in your question. The documentation for the Form.Close method tells us this:

When a form is closed, all resources created within the object are closed and the form is disposed.

[ . . . ]

The two conditions when a form is not disposed on Close is when (1) it is part of a multiple-document interface (MDI) application, and the form is not visible; and (2) you have displayed the form using ShowDialog. In these cases, you will need to call Dispose manually to mark all of the form's controls for garbage collection.

Notice that, in general, you won't find yourself ever having to call Form.Dispose manually from your code. It's impossible for a user to close a MDI child form when its MDI parent is not visible, and if you happen to close the form yourself in code when its parent is invisible, you can simply insert a call to Form.Dispose. When you show a form as a modal dialog using the ShowDialog method, you can conveniently wrap its creation and use in a using statement.

Now, recall that simply calling the Dispose method on an object only releases unmanaged resources and marks the object as available for garbage collection. It does not immediately release the memory claimed by that object. This is important, because it's exactly what your attempts at memory profiling were focused on. You know that the objects are being disposed, because you mention that the variables become unavailable to you (you say that you're "losing their values"). That's because you cannot access disposed objects. That doesn't necessarily imply, however, that the memory they claimed has been fully released. Doing so is the job of the garbage collector, which we've already established you're not supposed to monkey with. It will wait to release the memory until the application is either idle, or it desperately needs to reuse that memory. Otherwise, it will postpone collection, and that's still OK.

Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • There is a second exception to directly managing object lifetimes: limited non-memory resources. Eg. an open file will not be usable until GC has run unless you close it (this could be, and this is the better approach, done via a `using` statement). Such non-memory objects are not necessarily unmanaged (eg. a database connection could be implemented in 100% managed code). – Richard Mar 04 '11 at 10:56
  • 1
    @Richard: In those cases, the objects in question almost universally implement the `IDisposable` pattern, which I already accounted for in my answer. And a `using` statement is the correct approach, rather than any type of manual memory management (such as invoking the garbage collector yourself). I could have probably gone on a little longer, but I began to doubt very seriously that anyone would read all the way to the end as it is... – Cody Gray - on strike Mar 04 '11 at 10:59
  • accepted, and also noting "manual lifetime management" for me *is* `IDisposable` (which is why I used "lifetime"). But my comment was aimed at your paragraph starting "The only exception" having just said let the system do it itself. The problem of explaining this is that the answer has to say "let GC do its own thing except when" and the when needs to cover: syntactically scooped `IDisposable`, other `IDisposable` objects (eg. in fields) and directly using unmanaged (and thus the subject of finalisers); albeit I would probably just cover the last in passing as "advanced". – Richard Mar 04 '11 at 11:27
  • 1
    @Code Gray, nice, solid explanation. You can add some more links: Fundamentals of Garbage Collection - http://msdn.microsoft.com/en-us/library/ee787088(v=VS.100).aspx, Dispose, Finalization, and Resource Management - http://www.bluebytesoftware.com/blog/PermaLink.aspx?guid=88e62cdf-5919-4ac7-bc33-20c06ae539ae, How to identify memory leaks in the common language runtime - http://support.microsoft.com/kb/318263, How to detect and avoid memory and resources leaks in .NET applications - http://msdn.microsoft.com/en-us/library/ee658248.aspx – Nick Martyshchenko Mar 04 '11 at 12:50
  • @GodyGray. I read carefully all of your answer and of course I found it very scientific. But let's come back to my issue, which from the first time was the lose of varables value, and of course that hppens not after i dispose any form but during the work with the forms open. Thats why I suppose that my problem has to do something with the memory ?!?!?! – Lefteris Gkinis Mar 05 '11 at 12:00
1

make use of using block , which atomatically release memory

Using { resourcelist | resourceexpression }
    [ statements ]
End Using
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • 2
    That's not always possible. The resource inside `using {...` should be [`IDisposable`](http://msdn.microsoft.com/en-us/library/system.idisposable.aspx) – Oscar Mederos Mar 04 '11 at 09:33
  • @Oscar Mederos -- thats true thats y you require to implement Idisposable......... – Pranay Rana Mar 04 '11 at 09:37
  • But for most of the framework classes has IDisposable Interface, so in such cases it will be help and for winforms he must have to call it explicitly. –  Mar 04 '11 at 09:37
  • Please can you assist me with VB.NET because of the critical issue I need to have the exact code for it. – Lefteris Gkinis Mar 04 '11 at 09:39
  • @Lefteris Gkinis -- go to the link where you can get infomation in detail : http://msdn.microsoft.com/en-us/library/htd05whh.aspx – Pranay Rana Mar 04 '11 at 09:46
1

That's someting you shouldn't care about.

The .NET Framework Garbage Collector will do this work for you.

The .NET Framework's garbage collector manages the allocation and release of memory for your application. Each time you create a new object, the common language runtime allocates memory for the object from the managed heap. As long as address space is available in the managed heap, the runtime continues to allocate space for new objects.

Edit:

You have to make sure you're not using the resouces you wat to be free anymore. Garbage Collector's functionalities are located in the class GC under the namespace System.

In order to invoke it, you can do GC.Collect(), although I suggest you reading more about this topic and see some examples like this one

Oscar Mederos
  • 29,016
  • 22
  • 84
  • 124
  • Yes I will do that later today with my piece now I'm in my office work. – Lefteris Gkinis Mar 04 '11 at 09:48
  • @Lefteris Also, it would be great if you upload your code to a site like [Pastebin](http://www.pastebin.com) so we can take a look at it. – Oscar Mederos Mar 04 '11 at 09:51
  • I will do that later today, please – Lefteris Gkinis Mar 04 '11 at 09:58
  • 2
    This answer comes the closest of all to being correct; certainly in the first part. And while you're technically accurate that `GC.Collect` is how one would manually invoke garbage collection, there isn't enough bright red warning text surrounding that suggestion. I can *guarantee* that calling `GC.Collect` is **not** the solution here. – Cody Gray - on strike Mar 04 '11 at 10:17
  • Check Rico Mariani's When to call GC.Collect() - http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx – Nick Martyshchenko Mar 04 '11 at 13:22
1

Using as suggested by Pranay will work as it will by default call Dispose method. else explicitly you have to call this.dispose() after calling this.close() on your child forms. But be sure you are not going to use child form elements or value after close. Since dispose will finally clear everything.

MSDN example for disposing unmanaged resource

Imports System
Imports System.ComponentModel

' The following example demonstrates how to create
' a resource class that implements the IDisposable interface
' and the IDisposable.Dispose method.
Public Class DisposeExample

   ' A class that implements IDisposable.
   ' By implementing IDisposable, you are announcing that 
   ' instances of this type allocate scarce resources.
   Public Class MyResource
      Implements IDisposable
      ' Pointer to an external unmanaged resource.
      Private handle As IntPtr
      ' Other managed resource this class uses.
      Private component As component
      ' Track whether Dispose has been called.
      Private disposed As Boolean = False

      ' The class constructor.
      Public Sub New(ByVal handle As IntPtr)
         Me.handle = handle
      End Sub

      ' Implement IDisposable.
      ' Do not make this method virtual.
      ' A derived class should not be able to override this method.
      Public Overloads Sub Dispose() Implements IDisposable.Dispose
         Dispose(True)
         ' This object will be cleaned up by the Dispose method.
         ' Therefore, you should call GC.SupressFinalize to
         ' take this object off the finalization queue 
         ' and prevent finalization code for this object
         ' from executing a second time.
         GC.SuppressFinalize(Me)
      End Sub

      ' 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.
      Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean)
         ' Check to see if Dispose has already been called.
         If Not Me.disposed Then
            ' If disposing equals true, dispose all managed 
            ' and unmanaged resources.
            If disposing Then
               ' Dispose managed resources.
               component.Dispose()
            End If

            ' Call the appropriate methods to clean up 
            ' unmanaged resources here.
            ' If disposing is false, 
            ' only the following code is executed.
            CloseHandle(handle)
            handle = IntPtr.Zero

            ' Note disposing has been done.
            disposed = True

         End If
      End Sub

      ' Use interop to call the method necessary  
      ' to clean up the unmanaged resource.
      <System.Runtime.InteropServices.DllImport("Kernel32")> _
      Private Shared Function CloseHandle(ByVal handle As IntPtr) As [Boolean]
      End Function

      ' This finalizer will run only if the Dispose method 
      ' does not get called.
      ' It gives your base class the opportunity to finalize.
      ' Do not provide finalize methods in types derived from this class.
      Protected Overrides Sub Finalize()
         ' Do not re-create Dispose clean-up code here.
         ' Calling Dispose(false) is optimal in terms of
         ' readability and maintainability.
         Dispose(False)
         MyBase.Finalize()
      End Sub
   End Class

   Public Shared Sub Main()
      ' Insert code here to create
      ' and use the MyResource object.
   End Sub

End Class

(Update)[Check]

If your child form has the signature. These are by default added to a form.

'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
    MyBase.Dispose(disposing)
End Sub
  • @AmRan. i saw your proposal and I will do that with my piece in my own office, Now I'm in my work with lots on my head. I will contact with you today or tomorrow or after tomorrow. Have you see my update in my question? – Lefteris Gkinis Mar 04 '11 at 09:55
  • @AmRan. I follow your instractions (finally) and i saw that the only time the Class MyResource involves is at FormLoad and not at the FormClosed. Of course I have put all the Using refernces at the this sub FormLoad. now I need from you to assist me because the memory is not released. – Lefteris Gkinis Mar 04 '11 at 20:58
  • This code is intended for developers who are implementing custom classes that use unmanaged resources. Since you're not reinventing the entire Windows Forms library and creating your own `Form` objects, it's *extremely* doubtful that you'll have a need for any of this code mess. This has **absolutely nothing** to do with the original question, and misses a fundamental difference between the disposal of managed and unmanaged resources. Even worse, it ignores the original complaint that the memory usage doesn't appear to decrease. This won't change that. See my answer for details. – Cody Gray - on strike Mar 05 '11 at 10:23
  • @Cody : I agree with you but What if he has some custom class where unmanaged references are used. There is no provision in Winform that you have to write every thing in Form.cs or Form.vb class only. You can create you custom class too. –  Mar 05 '11 at 10:30
  • That's not described in the question. What if he has spyware installed on his computer that's inflating the memory requirements of his application's process? You can't play the what-if game here and keep your sanity. Obviously you're *allowed* to create your own custom classes, but reading the original asker's comments, it's even more clear that's not the issue here. Moreover, as I mentioned in my last comment, your answer still doesn't address the issue of the memory not being released. Calling `Dispose` is not going to make garbage collection happen, so no memory decrease will occur. – Cody Gray - on strike Mar 05 '11 at 10:53
  • I'm not trying to say that your answer is "wrong". My point is that it's "not helpful", which jives nicely with the tooltip on the downvote arrow. It doesn't apply to this question, it doesn't answer the issues that are being raised in the question, and it has a nearly 100% chance of leading the asker down the completely wrong path. – Cody Gray - on strike Mar 05 '11 at 10:54
  • @AmRan. Giving an answer to Cody I say that I'm not use any spyware for the moment. Additionally I say that I discover that every time I close a child form I was dispose the "StatusBar"but I wasn't dispose the form itself. Now I do that but the memory remeans uncleaned. Now I will put your UpDate in my code to see what it happens – Lefteris Gkinis Mar 05 '11 at 11:39
  • @AmRan. Don't forget that the problem was found in one of Local Network PC, not in my PC which has the SQL Server on it. And I do have four custom classes in my code one handles variables, other handles DB access procedures and functions, other handles reports etc. – Lefteris Gkinis Mar 05 '11 at 11:41
  • @AmRan. This "Protected Overloads Overrides Sub Dispose" is inside of the "...Desiner.vb" in every form i have !!!! – Lefteris Gkinis Mar 05 '11 at 11:54
1

You can use one of memory profilers available, e.g. ANTS Memory Profiler (take a look to Using ANTS Memory Profiler to track down a memory leak in a WinForms application). You can also use WinDbg but without experience it will be more complicated than specialized tool.

One of common "memory leak" reason is adding "external" event handler to form (e.g. to static or long living object), and not remove it on form destroy, so GC "thinks" you have reference to form and not collect its data.

Why and How to avoid Event Handler memory leaks ?

.NET Memory Leak Case Study: The Event Handlers That Made The Memory Baloon

Fundamentals of Garbage Collection

Dispose, Finalization, and Resource Management

How to identify memory leaks in the common language runtime

How to detect and avoid memory and resources leaks in .NET applications

Community
  • 1
  • 1
Nick Martyshchenko
  • 4,231
  • 2
  • 20
  • 24
  • @Nick. Please explain me what you mean EXTERNAL event handler. Because all my event Handlers are inside my program, as usual – Lefteris Gkinis Mar 04 '11 at 09:52
  • @Lefteris Gkinis, external to Form object (to another object's method inside same app). See Why and How to avoid Event Handler memory leaks - http://bit.ly/hkWf9z, Jon Skeet's answer and discussion – Nick Martyshchenko Mar 04 '11 at 09:58
  • 1
    @Nick: Please don't use obfuscated links on Stack Overflow. The comment formatting will automatically shorten lengthy URLs for convenience, but it's very nice to show what exactly we're being linked to. You have 600 characters at your disposal; this isn't Twitter. – Cody Gray - on strike Mar 04 '11 at 11:31
  • @Cody Gray, Ok. There are number of reason why this happens and I do that but if it not convinient I'll stop to shorten them. – Nick Martyshchenko Mar 04 '11 at 12:22
  • @Nick: I don't really understand what you mean. How would it ever be *more* convenient for you to run URLs through an obfuscation service first? Just copy and paste them directly from your address bar. Even if you have a browser extension that makes it very *easy* to do, I still can't imagine how it would be simpler. Either way, I would appreciate it if you would use the full address. Thanks. – Cody Gray - on strike Mar 04 '11 at 12:27
  • @Cody Gray, I treat http://bit.ly as shortening service with extended statistics, not as obfuscation. I have plugin in my Chrome which converts all link automatically with one click when I need and include page's title. Very convinient. It also shows full links in tip when you hover shorten links. I don't like links without titles, so I have to do one more copy&paste when doing manually. Also I interesting to know how much people really clicks my links. And I simply not really like how SO shorten links. Anyway I stop using it as this is not convinient for others. – Nick Martyshchenko Mar 04 '11 at 13:17
0

The garbage collector will do the work for you, so you really should not mind about it. You should have a more deep look inside if and only if you are using unmanaged resources ( com interop/PInvoke ).

Felice Pollano
  • 32,832
  • 9
  • 75
  • 115
  • I noticed that I'm loosing variables when the memory not released. I mean during my work and at the first entries my variables are OK but after some time passed I'm loosing my variables values, so i decide to release the memory myself If I Can – Lefteris Gkinis Mar 04 '11 at 09:33
  • @Lefterins: You can, but you should not: there is the garbage collector designed to do this job in the most efficient way. – Felice Pollano Mar 04 '11 at 09:36
  • Yes I use unmanaged resources. Please assist me What to do about. How to release. – Lefteris Gkinis Mar 04 '11 at 09:36
0

I'm no expert in VB.net but as far as I know it has a garbage collector. That normally means that closing the child windows does not free memory but if you remove all references to the child windows the garbage collector might free it in the next run.

Additionally, you normally can "ask" the garbage collector to run but it normally does "decide" by itself when to run.

Thomas
  • 87,414
  • 12
  • 119
  • 157
  • The memory Not released automatically by the garbage collector but always adds more and more memory. – Lefteris Gkinis Mar 04 '11 at 09:42
  • I don't know the .net garbage collector, but if it is similar to the Java one it will free the space for new allocations but normally that memory won't be returned to the OS until the program ends. If the garbage collector runs regularly the memory consumption should eventually settle at a certain level even if child windows are opened and closed (i.e. created and disposed) frequently. – Thomas Mar 04 '11 at 10:03