2012-01-04 53 views
1

默认情况下,当您创建Win-Form应用程序时,这是由Visual Studio生成的用于处理表单的代码。WinForms和事件处理程序

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

难道这还不够吗?还是我应该注销所有事件,这样的控件将随时被垃圾收集器收集的?

 if (disposing && (components != null)) 
     { 
      myButton.OnClick-= MyFunction; //may be here!! 
      // ... all events used 
      components.Dispose(); 

     } 

回答

0

不,垃圾收集器负责照顾它。由于表单实例处理完毕,该事件再也不会被提出,而该事件又处理了按钮。由于事件处理程序,表单和按钮之间有一个循环引用,但垃圾收集器没有问题。

+0

这是否意味着您不负责注销所有事件? – 2012-01-04 21:21:41

+1

@Hans Passant:根据我的经验,如果表单中使用的事件数量有影响,或者过于频繁使用,而不进行'取消订阅',则会导致内存泄漏。 – Tigran 2012-01-04 21:28:41

+1

是的,这就是它的意思。只有当事件源超过事件消费者时才需要它。从来没有一个表格和它的子控件的问题,他们都在同一时间死亡。 SystemEvents类的事件是必须手动取消订阅的事件的示例。 – 2012-01-04 21:31:51

0

如果这是经常close and open操作的主体形式,并用它里面事件的巨量,是重要注销所有事件。 Cuase事件肯定会消耗资源。

如果这是那些出现了一段时间,或者甚至可能永远不会出现,或者是,让我们说,上你的应用程序的MainForm,这并不重要从事件退订的形式。

怎么样一个place在哪里做,我会亲自退订里面,让我们的内线Closing倍率和Dispose()说。

+0

为什么不在'Dispose'中? .net中有一个非常强大的约定,当类实现IDisposable时,在实例上调用Dispose应该足以确保没有其他代表它的实体会处于不良状态。对于一个事件发布者来说,已经被放弃但永远不会退订的订户的存在是一个糟糕的状态 - “IDisposable.Dispose”应该阻止这种状态。 – supercat 2012-01-04 21:22:55

+0

@supercat:只是为了尽可能快地摆脱它们,不要等待GC调用,以防万一用户没有明确地调用它,或者通过代码构造('using'语句)调用它。在'Dispose()'中使用是一个有效的解决方案,顺便说一下,事实上我没有拒绝它像一个不可接受的,只是给我的主题。 – Tigran 2012-01-04 21:25:23

+0

我并不是故意暗示在调用Dispose之前不应断开事件,而是如果在调用Dispose之前没有处理任何事件,Dispose应该将它们关闭。请注意,Finalize()对于清理事件通常是无用的,因为直到发布事件的对象已被放弃,从而使订阅无效,并且因为即使一个对象上的Finalize()显示某个其他对象事件应该断开,事件退订是唉,不保证线程安全。 – supercat 2012-01-04 21:50:24

2

表单必须从实体中取消注册所有会超过表单的事件。如果表单从与表单具有相同生命周期的实体注销事件并不重要。无论出于何种原因,正常的教义似乎是“不担心注销事件,除非事件重要”。我认为让所有订阅事件的对象取消订阅Dispose会更清晰,但不幸的是,vb.net和C#都没有提供任何即使远程清理的方法来完成此操作。使用实现IDisposable的依赖关系,可以将构建包装在例程中,该例程将新创建的项目添加到稍后将清理的事项列表中。然后可以通过简单地在列表中的所有内容上调用Dispose来执行所有必要的清理。不幸的是,从.net的角度来看,没有好方法来编写一个通用程序,它将同时订阅一个事件并返回一个Action<>,IDisposable或其他可用于取消订阅的对象。