Search code examples
c#multithreadinggdi

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.


Solution

  • 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.