9

我有一个允许编辑产品信息的程序。我注意到关闭编辑表单后它没有释放内存。经过一些研究,我偶然发现了这个问题,它提到问题可能在于它挂在事件订阅上。

这对我来说是有意义的,因为这个表单上有大约 100 多个控件,其中许多是自定义的,带有由其父控件订阅的自定义事件。这会创建一个相当大的事件订阅层次结构。所以我寻找了一种方法来发布这些,并找到允许您取消订阅该事件的方法。

问题是,我有大量订阅。我真的必须在表单关闭时一个一个地手动取消订阅每个事件,还是至少有一种方法可以一举释放它们,或者循环它们?

4

2 回答 2

6

记住这一点:左边的+=对象使包含右边方法的对象保持活动状态+=。也就是说,引发事件的对象使处理事件的对象保持活动状态,即使处理事件的对象(例如表单)已被释放。

所以你需要确保的是所有的事件引发者都已经离开了。

但是,如果所有事件引发器恰好是订阅这些事件的同一个类中的控件,则在关闭表单时Form,您无需手动取消挂钩所有事件处理程序。

这是因为引发表单订阅的事件的控件与表单本身具有相同的生命周期。

如果您订阅的对象引发的事件比正在订阅的对象的生命周期长,您只需要担心。然后订阅对象(表单)在处理它(表单)时需要取消订阅。

于 2013-05-03T15:10:21.523 回答
4

这取决于您的表单及其事件将存在多长时间。

但是,您可以循环访问表单中的控件,释放事件。如果您意外删除了一个不存在的事件 - 不用担心,它不会引发异常。

例如,这是摆脱所有 TextBox.KeyDown-Events 的方法:

  private void frm_FormClosed(object sender, FormClosedEventArgs e)
    {
    foreach (Control tb in this.Controls)
    {
        if (tb is TextBox)
        {
            TextBox tb1 = (TextBox)tb;
            tb1.KeyDown -= TextBox_KeyDown;
        }
    }
于 2013-05-03T15:13:17.157 回答