views:

104

answers:

3

I am trying to reduce memory usage of a winForm application.

There is a main form and a setting form in the application. When "Setting" button been pressed, the setting form will popup as a modal form, the Setting form will load app.config data from config file and read them to memory as Hashtable. After the setting form closed, it will call Dispose method inherented from Windows.Forms.Form. The Dispose method is as simple as set the Hashtables and app.config object to null.

Show SettingForm as modalform:

private void btnSettings_Click(object sender, EventArgs e)
    {
        frmConfig form = new frmConfig();
        form.StartPosition = FormStartPosition.CenterScreen;
        //MessageBox.Show(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase));
        form.ShowDialog(this);
        form.Dispose();
    }

Dispose method:

 protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
            // Release managed resources
            Logger.Verbose("Disposing SettingForm");
            mySetting = null;
            testFtp = null;
        }
        base.Dispose(disposing);
    }

Note: mySetting is a instance of Class with all the app.config data been load into Hashtable, and testFtp is a custom object for ftp function. Should I implement Dispose method for this two class and using

mySetting.Dispose();
testFtp.Dispose(); 

instead of set them to null, as they are themself/deal with unmanaged resources?

But each time push the "Setting" button and close the setting form will increase private Byte for a few hundreds K. Memory leak? How could I get rid of it?

+1  A: 

The memory may not be getting released because of some other piece of code too. Since you have not provided much details, I'll assume right now that everything else is optimal.

The objects that you are working with are collected by garbage collector (as you know it). But they may not be released from memory when you want it. .NET objects are better left to garbage collector.

As per why the memory may not be getting released, you have the answers here.

Setting object reference to null doesn't make much difference. On the other hand, I've personally recorded some times, objects coming back alive (and pushed to old generations) because you're using them while setting null to same. It's another form of interference with GC, but your choice.

You may not need to implement IDisposable, but if you are working with streams, OS handles, unmanaged resources, you should then.

Edit:

The memory usage may be high, but it's GC's responsibility to free it as long as you do not keep references alive. So, if you have taken every precaution, it still may seem that your application is consuming lot of memory. That is acceptable as freeing the unreferenced objects is garbage collector's responsibility.

Nayan
According to this Article, I found it is very useful for newbie as me by the way, http://www.dotnetfunda.com/articles/article625-best-practices-no-5--detecting-net-application-memory-leaks-.aspx Consistently increase in Private Byte memory usage indicate a unmanaged resources leak, in that case I have to make sure they are properly release, which means I need IDisposable all the way down I think?
pstar
That's a great article that I missed. Thanks for that! Ok, if you "know" that it's unmanaged memory leak, then find out locations where the unmanaged memory is getting allocated. You can implement the `IDisposable` interface and release the object's unmanaged members. But also make sure that the codes whose scope is limited to a function of so, are also releasing the memory. They cannot be freed in Dispose method. For example: closing a stream in a function - this can be handled only in that function! All the best!
Nayan
A: 

Why do you think it's a leak? GC is not obliged to free memory instantly, under some circumstances it may never actually perform the collection and that would be okay.

If you really need these kilobytes freed immediately, you might force GC to perform the clean-up just after the disposals, but it's a costly operation in general and may affect overall performance.

vines
+1  A: 

As you suggested near the end of your question, I would recommend implementing IDisposable on mySetting and testFtp. You should see better cleanup of resources once you have implemented the following:

 protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
            // Release managed resources
            Logger.Verbose("Disposing SettingForm");
            mySetting.Dispose();
            testFtp.Dispose();
        }
        base.Dispose(disposing);
    }
 }

Small edit: Based on Nayan's answer and the answer he links to: I'd highly recommend the implementation of IDisposable. Using Forms and deriving from the Forms class screams, "Check for the need to implement IDisposable." This does not mean that your code should be implementing it, just that you should really check to make sure you don't need it. Forms typically have a lot of events published and subscribed to. Forms are also notorious for becoming a catch-all resource bucket, IMO.

dboarman