在本地范围内具有事件处理程序的 GDI 对象

GDI Objects With Event Handlers in Local Scope

我有一个快速的问题,但我无法在其他地方找到答案。

我们有一个大型 4.0 桌面应用程序(考虑 3 个解决方案之间的大约 100 个项目)遇到 10k+ GDI 对象问题。显然我们在某处有泄漏。我最近一直在进行 lot 测试,以找出可能是什么问题。其中一些是 .NET,例如,TabControl 的每个新实例,即使被处置,似乎都会留下一个 GDI 对象(每个 open/close 的形式从 79 个对象增加到 80,然后是 81,然后是 82等),但显然我们的用户不会每天打开带有选项卡控件的表单 10,000 次。

关于我的问题:我是否必须为本地范围代码释放事件处理程序,如下所示:

            UserLoginManager loginManager = new UserLoginManager();
            loginManager.LoginFailed += HandleFailedLogin;
            loginManager.LoginSuccessful += HandleSuccessfulLogin;

            loginManager.LogUserInAsync(this.UserNameTextBox.Text.Trim(), this.PasswordTextBox.Text.Trim());

我问这个是因为我不确定如果有事件处理程序分配给一个在应用程序的生命周期内保持打开状态的表单,对象是否会被正确地 GC。

GC 只追逐一个方向的引用。您正在注册的事件处理程序委托将引用表单(如果它们是实例方法),并且事件本身包含对委托的引用。但是,如果没有任何东西持有对 UserLoginManager 的引用,那么它将符合收集条件,并且它(传递地)持有的引用不会使其他对象保持活动状态。

事件处理程序和泄漏的风险是相反的方式 - 如果您有一个暴露事件的长期对象并且您有希望短暂的对象- 如果那些 "should be short-lived" 对象注册了事件处理程序并且未能在 之后注销它们,那么 将延长它们的生命周期。