GDI Objects With Event Handlers in Local Scope - c#

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.

Related

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.

When to use Weak Events?

I was refering MSDN tutorial on weak events. I understood the basics. I am working on a non-WPF project and my class is exposing certain events. My question is that does the weak events
completely replace old event pattern? Is it good to use it every classes that is exposing events? What are the side effects of using weak events liberally?
Based on the reading I have done, there does not appear to be any specific negatives to using WeakEvents, except for the fact that it is more verbose to do so. Additionally, you should be able, in most cases, to manually unregister from events when you no longer need them. In some cases, this won't be possible. For example, the MSDN page you reference mentions when you should use WeakEvents:
http://msdn.microsoft.com/en-us/library/aa970850.aspx
Certain scenarios inherently lend themselves to the application of the weak event pattern. One such scenario is data binding. In data binding, it is common for the source object to be completely independent of the listener object, which is a target of a binding. Many aspects of WPF data binding already have the weak event pattern applied in how the events are implemented.
The only person who has presented any type of negative to them is this blog:
http://blog.catenalogic.com/post/2011/11/23/A-weak-event-listener-for-WPF-Silverlight-and-Windows-Phone-7.aspx
There are a few downsides about using a weak event listeners in general:
It’s notation is ugly, the “original” .NET way looks way better
You have to name the event by string, that sucks (if you know a better way, contact me!)
It can only handle events with a handler of EventHandler
You become a lazy developer not caring about subscriptions
Essentially, they should be used for events that your objects will subscribe to for the entire length of their existence, and only disconnect from when the objects are disposed. For everything else, using the traditional events and registering/unregistering the events manually is preferred.
There are two issues that must be considered with weak events:
Weak events allow subscribers to subscribe to events (messages) even without knowing the identity of the class raising the event. In some cases that may be desired even necessary. However, in some cases that can introduce unnecessary complexity and a level of indirection that makes the code harder to manage or control at run time.
The major downside of using weak events is that it may encourage developers to neglect the part where they unsubscribe from events (messages). In that case event handlers may be invoked even after the subscribers "go out of scope". Consider a subscriber that does not explicitly unsubscribe and that becomes garbage collectable but was not yet garbage collected. The weak event manager will not be able to detect that state and because of that it will still call the event handler of that subscriber. This can lead to all kind of unexpected side effects.
See more details at The Weak Event Pattern is Dangerous.
See this source code that illustrates this issue using the MvvMCross messaging plugin as a weak event manager.
When to use weak events?
From MSDN
Listening for events can lead to memory leaks
So you should use weak events with the purpose of avoiding those leaks
Is it good to use it every classes that is exposing events? What are the side effects of using weak events liberally?
See Why is the implementation of events in C# not using a weak event pattern by default?. Leaking from "strong" events is not that usual, weak events come with a performance cost and have a semantic difference that may not be desired in every context, misuse of a weak reference can cause the event to intermittently not to fire (in contrast to misusing a normal event causing a memory leak)
Example memory leak that could be avoided
Static classes and Singletons are villains when talking about memory leaks, when they acquire a reference to some other object they will prevent the object from being garbage collected, and thus, leak the object forthe lifespan of the application, here is an example where I met with the need for a weak reference to avoid a memory leak
First of all, weak events are not always necessary, like others have been saying only when the source object outlive the subscriber. If that is the case, then yes, you should use it, this is what people call The Weak Event Pattern.
The side effects are just that you will have to write more code. Microsoft provides the WeakEventManager class and in WPF exist some specific implementations, but you can create your own inheriting from the base WeakEventManager.
The way it works is by using weak references from the source object to the listener so this relationship doesn’t stop the GC from collecting these objects. For some specific applications this can solve a lot of performance issues.

How to clean up memory used by many user controls

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?

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()

Categories