Page 1 of 1

UserPreferenceChangedEventHandler causing memory leaks

Posted: Mon Oct 26, 2009 9:21 pm
by acss_support
Using the profiler it has been determined that UserPreferenceChanged event handler causing memory leaks when we use the GridView control in our application.

Q. Why is UserPreferenceEvent handler holding the objects in the memory and causing leaks when that event is not even created any where in the code explictly?

Do we have to unreference the event explicitly ? If so, why and where we have to unreference it ?

We are looking for a generic solution for the above issue with a concrete reasoning on why it's a fix. Is there anyone who can help ?

**********************************************************
Additional Details:
**********************************************************
The following is the analysis of our finding on UserPreferenceChanged event handler causing memory leaks.

1. Object using DataGridView not Disposed and UserPreferenceChangedEventHandler NOT Unreferenced (Current state in our application)

When the object in which the grid control is used is NOT disposed without unreferencing UserPreferencChangedEvent handler in the contructor or Dispose method then we see UserPreferencChangedEvent handler causing the leaks. This is the current state of our code in the application and we are experiencing the memory leaks.

We see that UserPreferenceChanged event is causing memory leaks in our code whenever we use DataGridView control by holding the objects in the memory.

Q. Why is UserPreferenceEvent handler holding the objects in the memory and causing leaks when that event is not even created any where in the code explictly?

2. Object using DataGridView Disposed and UserPreferenceChangedEventHandler NOT Unreferenced
When we dispose the object in which the grid control is used without unreferencing UserPreferencChangedEvent handler in the contructor or Dispose method then we are NOT seeing leaks caused by the UserPreferencChangedEvent handler created through that particulat object. This solution is per Object level i.e this only works when the objects in which this DataGridView control is used is part of the memory leaks. This is not a common solution.

As a solution, we didn't like disposing the object explicitly and fix the leaks caused by the UserPreferenceEvent handler because of the following reasons
a. All my objects are managed and as a programmer I am not responsible to dispose the objects explictly by either calling Dispose method explicitly or with using statement. I believe, it's the job of the Garbage collector to identify the unreference objects and clean them all.
b. Some objects are getting disposed by calling the Dispose method in the Designer file without calling it explictly (I believe Forms and UserControls implements IDisposable internally) and we are not sure when we have to Dispose explicitly and when NOT.
c. When new development happens and new screens added, this control is going to cause the leaks which we have to go through the process of identiying it and fixing it.

3. Object using DataGridView NOT Disposed and UserPreferenceChangedEventHandler Unreferenced in DataGridView 's Contructor
When we unreference the UserPreferencChangedEvent in the constructor of the DataGridView without disposing the object explicitly in which this control is used then we don't see any memory leaks with respect to the DataGridView control. This solution works as a common solution at control level i.e no matter in how many objects you use this usercontrol, it cleans the memory when you are done since it already unreferenced in contructor.

As a solution, though it works, we don't like to unreference UserPreferenceEvent handler in the contructor of the control because of the following reasons
a. We haven't created the UserPreferenceEvent handler explictly anywhere in the code and so we are not conformtable to unreference it explictly.
b. Even though we go into that direction as a temperory solution, we definetely don't want to unreference the event in the contructor of the control at the time of creating the object.

4. Object using GenlGrid NOT Disposed and UserPreferenceChangedEventHandler Unreferenced in DataGridView Dispose method
When we unreference the UserPreferencChangedEvent in the Dispose method of the DataGridView without disposing the object explictly in which this control is used then memory leaks are NOT getting fixed. The code in Dispose method only executes when the object in which it is used is disposed properly. So, this doesn't fix any memory leaks.

***********************************************************

Posted: Tue Oct 27, 2009 9:46 pm
by Andreas Suurkuusk
As I understand it, you have GenlGrid instances that are no longer in use, but they are kept alive by the UserPrefrencesChangedEvent. Is that correct?

There are several disposable classes in the System.Windows.Forms namespace that require the instances to be properly disposed in order for them to be GCed. The DataGridView is one of these classes. If a class implements IDisposable, it is an indication that there is some additional cleanup to be performed, which the GC might not be able to do. In this case, you should try to call Dispose on its instances (e.g. scenario 2 in your description).

A windows forms control will be disposed when its parent is disposed, but if the control has been removed from the parent (and possible replaced by another control), it will not be automatically disposed. In this case it is your responsibility to dispose it. If your GenlGrid instance has been removed from its parent (and you will not re-add it), you can safely dispose it (even if it was created by designer core).

I would not recommend that you use scenario 3 to avoid the memory leak, as you will alter the implementation of the DataGridView and prevent it from being updated when user preferences actually change.

Posted: Wed Oct 28, 2009 3:29 pm
by acss_support
Yes you are correct. The grid instances that are no longer in use are kept alive by the UserPrefrencesChangedEvent.

We are using many user controls in our application and Dispose method on those controls are automatically called when we close the form on which these controls are placed (Designer.cs file have a Dispose method which will be called). But few forms never call the Dispose method automatically even after closing it or when go out of scope and we unable to find the reason's for such behavior. Scenerio 2 in my description is not a generic solution because of the reason I explained and it's a pain to identify and fix every corner of our application. Also, we had bad experiences for calling Dispose on the controls or forms explictly and we have decided not to call any where in our code.