How to clean up memory used by many user controls - c#

I have many user controls where I add only one of them each in a panel but first clear the panel from the previous one.
I create a new instance of the user control when I want to add it in the panel, and Dispose() the other user controls and set all the references to null to allow the garbage collector to delete them.
For example:
// Declare the variables globally
ViewBasicInformation control1 = null;
AddBasicInformation control2 = null;
// Code inside Button
Panel.Controls.Clear();
control1.Dispose();
control1 = null;
control2 = new AddBasicInformation();
Panel.Controls.Add(control2);
However my memory usage keeps increasing, how do I release this memory?
And for more information ... Every user control consumes a class that makes a connection to a smart card and executes some commands to read and write to the card.
I also have a backgroundworker that detects when the card is inserted or ejected.

The .NET runtime uses garbage collection - I urge you not to manage memory yourself.
I would expect memory to go up initially - if it never goes down, you have dangling references somewhere. Chances are you are subscribing to events and when the objects that have been subscribed are no longer needed you do not unsubscribe from these events. This is the most common cause of memory leaks in .NET applications (though dealing with unmanaged code is a close second).
Make sure you unsubscribe from any control event that you have subscribed to before you clear out the reference to it.

Regardless of the garbage collector being quite clever about when it has to run and when it doesn't need to, there are a number of error sources where you effectively get yourself into memory leaks based on event handling and different lifetimes of objects. This has been a subject on SO before (e.g. here) and I have written a little bit about some mistakes we did on one project that was the cause of memory leaks here: Do you think your Windows.Forms Application has no memory leaks?

Related

GDI Objects With Event Handlers in Local Scope

I have a quick question that I have been unable to find an answer elsewhere.
We have a large 4.0 desktop application (think around 100 projects between 3 solutions) that is experiencing 10k+ GDI Object issues. Obviously we have leaks somewhere. I've been doing a lot of testing lately to figure out exactly what might be the issue. Some of it is .NET, for instance, every single new instance of a TabControl, even disposed, appears to leave behind one GDI Object (each open/close of the form increased from 79 objects to 80, then 81, then 82, etc.) but obviously our users are not opening up forms with tab controls 10,000 times a day each.
Onto my question: do I have to release event handlers for local scope code such as below:
UserLoginManager loginManager = new UserLoginManager();
loginManager.LoginFailed += HandleFailedLogin;
loginManager.LoginSuccessful += HandleSuccessfulLogin;
loginManager.LogUserInAsync(this.UserNameTextBox.Text.Trim(), this.PasswordTextBox.Text.Trim());
I ask this because I don't know for sure if the object will be GC'd correctly if there are event handlers assigned to, say, a form that remains open for the lifetime of the application.
GC only chases references in one direction. The event handler delegates you're registering will have a reference to the form (if they're instance methods), and the event itself holds references to the delegates. But if nothing is holding a reference to the UserLoginManager then it will be eligible for collection and the references it is (transitively) holding won't keep other objects alive.
The risk with event handlers and leaks is the opposite way around - if you have a long-lived object that exposes events and you have objects that want to be short-lived - if those "should be short-lived" objects register event handlers and fail to unregister them later than that will prolong their lifetimes.

How soon after disposing is memory available?

Is it instantaneous after the GC runs?
I was monitoring Memory (Available MBytes) using perfmon while running an application I'm working on. As I loaded files I could see the Available MBytes going down as expected, but as I closed them it didn't go back up so I'm wondering if I am not disposing correctly or if there is something else that affects this.
When a file is loaded:
the contents are stored in some objects
a new instance of a UserControl is created
a new TabPage is created
the UserControl is added to the TabPage
the TabPage is added to the TabControl
Reading on SO I saw that one of the most common things that can cause Memory Leaks is not unsubscribing from event handlers and so I made sure I did that in my UserControl's dispose method. I subscribe to the 'RemovingTab' event of the TabControl but the TabPages themselves have no attached handlers.
When closing a file, I remove stored instances of the objects and call dispose on both the UserControl and the TabPage. I tried running the CLR profiler (which I haven't had any experience with) and it said there was no GC runs.
Another common source of memory not being released is holding onto unmanaged resources, open files being one example.
The memory is available after the GC cleans up whatever is using it. Not every GC run results in memory being released. Any object that survives at least one GC run can end up living a long time because it's no longer in generation 0 - those could end up being around until the app actually needs more memory than is currently available to it. Large objects (larger than 85kb, as far as I remember) are stored on the large object heap which also isn't part of every GC run.
Your best bet is to look at what is actually holding the memory. Use the Visual Studio performance tools or try PerfView. Once you know what is actually holding the memory you'll be in a better position to figure out how to get it released.
Is it instantaneous after the GC runs?
No. As a matter of fact, depending on the memory pressure of your particular application, the GC might not free up any memory during the whole lifespan of your application.
Reading on SO I saw that one of the most common things that can cause Memory Leaks is not unsubscribing from event handlers and so I made sure I did that in my UserControl's dispose method.
Yes that is a common cause.
When closing a file, I remove stored instances of the objects and call dispose on both the UserControl and the TabPage. I tried running the CLR profiler (which I haven't had any experience with) and it said there was no GC runs.
The GC is very good at doing what it's supposed to do and it has been fined tuned to extremes. If it doesn't run its probably because it has decided that it doesn't need to run. Therefore, when the memory is freed up by the GC is up to the GC to decide and, if I'm not mistaken, is implementation defined, so it is not something you can rely upon.
And last but not least, the IDisposable pattern is not, by any means, a deterministic pattern for reclaiming memory; that is most definitely not the pattern's goal.

Memory Leak questions

I've been reading a lot about this since I've been asked to fix a C# application that has memory leaking problems, but I haven't found an answer for these 2 issues:
Consider the following code:
private static ArrayList list = new ArrayList();
public void Function()
{
list.add(object1);
list.add(object2);
//didn't call clear() prior to reusing list
list = new ArrayList();
}
Since the list wasn't cleared before creating a new one, will this generate some sort of garbage that won't be released after the static list itself is disposed?
The second issue is regarding Form.Dispose(). I see that a lot of controls available on designer view (i.e. labels, picture boxes) require disposing. It's seems as though calling Dispose() on a Form causes all of these types of controls to be disposed also (correct me if I'm wrong), which is odd since the designer adds an overriden void Dispose(bool disposing) method which does no such thing. I'm assuming that this happens at the void Dispose(bool disposing) method of the base Form class.
The problem with the above is that it is not very clear to me what I need to do to ensure that all of the Form's resources are disposed correctly. I do not understand how the Form knows which objects it needs to dispose. For example, if in my form I have a field which is a custom IDisposable object, will the Form know that it needs disposing? Or should I add the code necessary to release the object myself?
Also, if I do need to add the code to dispose certain objects, then how do I deal with the fact that the designer has already overriden the void Dispose(bool disposing) method? Should I edit the designer generated code or is there a cleaner way to do this?
I hope that this wasn't to confusing, it's a bit hard to explain. Thanks
No, that's not a leak. When the garbage collector goes searching for object references, it won't find a reference to the original ArrayList anymore. You replaced it. So it will automatically destroy that original ArrayList object, as well as all of its elements if they are not referenced anywhere either.
The Form class knows how to dispose itself, as well as all the controls that are child windows on that form. This happens when the user closes the form, the WM_CLOSE message that Windows sends triggers this code. The Form.Controls collection helps it find the reference to all child controls so it can dispose them too.
However, this will not happen if you remove controls from the form yourself. Now it is up to you to call Dispose() on them. Particularly the Controls.Clear() method is dangerous. What is unusual about it is that this causes a permanent leak, the controls you remove are kept alive by the 'parking window'. Which keeps the window handle alive so you can move them elsewhere, on another container window for example. If you don't actually move them, they'll stay hosted on that parking window forever. No other classes in the framework quite behave this way.
This leak is easy to diagnose with Taskmgr.exe, Processes tab. View + Select Columns and tick USER Objects. If this steadily goes up while your program runs then you're leaking controls.
What is the scope of your Static arraylist. Looks to me that it has a form scope. If it is, it will not be disposed since static objects are always considered rooted and has an application life time. In my experience, statics always take more memory and get promoted to gen 2 because of this fact. If you have any doubts, take a .net memory profiler and check it out. You can also take memory dumps and analyze it using windbg to figure out the real cause of the leak.
In many memory-management frameworks, garbage-collected and otherwise, freeing up memory within an application does not generally cause the application to release that memory, but instead record the fact that the memory should be available for future requests. Part of the idea behind garbage collection is that when user code asks for memory and the application knows that it has at least that much immediately available, neither the code nor the application will care about whether any memory not needed for that request is "allocated" or "free". When the last reachable reference to an object is destroyed or becomes unreachable, the object effectively ceases to exist right then and there, but there's generally not much purpose in trying to reclaim memory formerly used by non-existent objects until such reclamation is either required to fulfill an allocation request, or the "memory freed per time spent" ratio is as good as its likely to get.
Note that for the system to reclaim the memory associated with an object, it is absolutely imperative that no reference of any sort exist to that object. If there exist any reachable weak references to an object which is not otherwise reachable, the garbage-collector must invalidate all such references (so they no longer identify the object) before the space used by the object can be reclaimed. If an otherwise-unreachable object has a registered finalizer, the system must put the object on a queue of things needing immediate finalization (thus making it ineligible for reclamation) and unregister the finalizer.
Weak references and the references used for finalization are both invalidated automatically by the GC when all other references to an object are abandoned, and thus do not cause memory leaks. There's another kind of reference, however, which can cause nasty leaks: event subscriptions from publishers that outlive subscribers. If object A subscribes to an event from object B, object A cannot be garbage-collected unless either (1) it unsubscribes from the event, or (2) B itself becomes eligible for garbage-collection. I find myself puzzled at why Microsoft didn't include some means of automatic event unsubscription, but they didn't.

Destroy controls

I use a for loop to generate some controls. Each control presents a special visualisation. I can not use controls like ListBox or somethink like that. I must use my approach. The generated controls are hosted in a Canvas. After a while, some controls are not longer needed. Some controls must be removed. I can manually remove a controls via
c.Children.Remove( ... );
this line. How do I determine that the controls was really collected from be garbage collection? Maybe the control already exists in the memory ... . How do I ensure this?
The problem is that I generate data in tons!
Thanks in advance! :-)
So if you call to Destroy the control, and you haven't maintained any other references to the control in memory (like in a hashtable of controls or something), then the GC will collect it.
Don't try and force the .NET GC to do something fancy, let it do its work in its own time as the library authors designed it. If you Destroy it, it will be gone, in due time.
Lastly, if you're concerned that it's still consuming memory, it will be time to start profiling your code, like for instance with RedGate Ants.
Depending on the control that you're using maybe you need to call Control.Dispose() to free all resources. Be careful is you are using unmanaged resources (Learn more)
I think this is not your case.
Then the garbage collector will collect the object for you.
Also, this article about how Garbage Collector works could be very interesting:
http://www.codeproject.com/KB/dotnet/Memory_Leak_Detection.aspx
You don't really need to. That's the sense of garbage collection: as soon as there are too many dead objects, garbage collection jumps in and cleans them out. Or doesn't clean: the GC knows better what and when to remove.
As long as nothing holds a reference to a control, the garbage collector will get rid of it and you have nothing to worry about. Usually, removing a control from the collection that contains it all you need to do.
But you must be careful with event handlers. If object A subscribes to an event that object B raises, object B holds a reference to object A. If your controls subscribe to, say, Canvas.IsEnabledChanged, you can remove them from the Canvas, but the Canvas will still hold a reference to them so that it can notify them when IsEnabled changes, and they won't be garbage-collected. This is the most common cause of "memory leaks" in .NET applications. (They're not really memory leaks, but they might as well be.)
if you're sure the objects arent referenced anywhere anymore, you can force a call to the garbage collector with gc.Collect()

how to free Memory ( User Control )

I am using WPF.
After adding user controls dynamicaaly at runtime, How to Dispose that user control.
Because there is no Dispose Method for User Controls. i dont want to wait untill Garbage Collecter runs.
Even if you were able to dispose it, that wouldn't free memory. Dispose isn't about releasing memory - it's about releasing non-memory resources (e.g. GDI handles). I would assume that if the class doesn't implement IDisposable, it doesn't have any non-memory resources to release.
I think your design is flawed.
If you still have a reference to something then you shouldn't try to free the memory anyway.
Once something is actually no longer alive (no further references to it) it is effectively available memory in that, the next time you need some memory which cannot be supplied without a GC it will become free[1] and available.
Your design is not wasting memory, it is simply churning memory. This in itself may be problematic but it does not waste memory. If your design holds onto references to controls after they are no longer needed that wastes memory, but you cannot 'band-aid' over the problem by 'deleting' them. You need to tackle the root cause of passing these controls all about the place in a manner that makes their life cycle hard to control.
[1] barring finalizers which do not apply here
Is there a reason you don't want to wait for the GC? If you remove the control from it's parent so there's no references to it then the GC will eat it, there's no need to dispose of it manually.
Thanks Steve.
Firstly i add numerous UsrCtr Elements on my Application Frequently. so if they are't removed instanteously, Huge memory will be wasted.
Actually i am using ForEach Loop at several places to iterate all the elements on the Application (WinForm) , so this loop still show the UserCtrs (After removing the UserCtr as chld)
Further more i also pass the refrence of the UserCtrs to several other places in my project through the Custom Defined Events and Delegate. So if add it at one Place on Main Form, still there may be possiblity that Refrence for the User Control Exists some other Place in the Project.

Categories