How to release the occupied memory
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 wa开发者_Python百科nt 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).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 usingShowDialog
. In these cases, you will need to callDispose
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.
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
make use of using block , which atomatically release memory
Using { resourcelist | resourceexpression }
[ statements ]
End Using
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
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
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 ).
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.
精彩评论