Search code examples
vb.netwinformsresourcesdispose

Totally form Disposing and free up memory


I already read a ton of topics "class disposing" about and I did understand how to do it and it works fine! Meanwhile "form disposind" is not same and resources still leaking!

What I am doing:

Initializing form by "using" method:

Using f as New Form
    f.ShowDialog()
    'my code
End using

In this case by "end using" form terminated with "Dispose" method.

For example:

I have a form which have a class (it contain parameters and other classes). On initialization form event, form (itself) take 12Mb of memory (I measure it in process explorer) and plus my class take 10Mb (which Disposable and also disposing before Dispose form on Dispose event). After my form disposed (I measure it again) I see my class disposed and resources (of class) are free totaly, the form is not freeing resources. In other words I kill 10Mb (of class) BUT DON'T kill 12Mb (of form).

My Dispose code:

Private Sub Form_Disposed(sender As Object, e As EventArgs) Handles 
Me.Disposed
    If Not fDisposed Then
        MyPersonalClass.Dispose()'class
        MyPersonalClass = Nothing
        fDisposed = True
        GC.SuppressFinalize(Me)
        GC.Collect()
        Finalize()
    End If
End Sub

It's very bad. If most of time I working with these forms and if they are don't free resources after dispose, each opened form will be leave approx 10-12Mb in memory after closed. And if I open my form 100 times it will freezes more then 1Gb of memory.

What I doing wrong?


Solution

  • I'm not really familiar with VB, but I think it will do things similar as to how they are done using winforms for C#

    The easiest way to make sure that all Disposable objects of A Form are disposed when the form is disposed, to keep a collection of Disposable objects. You could use the existing class Sytem.ComponentModel.Component class for this. The disadvantage is that it only accepts objects that implement interface IComponent. If you have only a few classes that must be disposed that don't have this interface yet, this is the easiest method. Otherwise design your own DisposableCollection

    class DisposableCollection : List<object>, IDisposable
    {
         public bool IsDisposed {get, private set} = false;
    
         private IEnumerable<IDisposable> DisposableItems => this.OfType<IDisposable>();
    
         public void Dispose()
         {
             if (!this.IsDisposed)
             {
                   // Dispose all disposable items
                   foreach (IDisposable disposableItem in this.DisposableItems)
                   {
                       disposableItem.Dispose();
                   }
                   this.disposed = true;
             }  
         }
    }
    

    Usage:

    class MyForm : Form
    {
         private readonly DisposableCollection disposables = new DisposableCollection();
    
         public MyForm()
         {
              // create and add all your items to disposables
         }
    
         protected override void OnDisposing(bool disposing)
         {
               this.disposables.Dispose();
         }
    }
    

    If desired you can add event handlers to notify others that the object is being disposed