当事件触发并尝试在不再存在的对象中执行事件处理程序时会发生什么?

时间:2009-05-29 06:58:30

标签: c# events event-handling

在一个ClassA中,我有一个计时器对象。在这个类中,我为timer elapsed事件注册了事件处理程序。在另一个类ClassB中,我有一个用于timer elapsed事件的公共事件处理程序。所以我在ClassA中从ClassB注册事件处理程序,如下所示:

myTimer.Elapsed += ClassBInstance.TimerElapsed

如果我要创建ClassBInstance的新实例,并且当ClassB的事件处理程序的前一个实例仍然与计时器的Elapsed事件绑定时,会触发计时器已过时事件会发生什么?

例如:

ClassB classBInstance = new ClassB();
myTimer.Elapsed += classBInstance.TimerElapsed

classBInstance = new ClassB();
myTimer.Elapsed += classBInstance.TimerElapsed

4 个答案:

答案 0 :(得分:11)

AFAIK,只要注册了事件,ClassBInstance就不会被垃圾收集,因为事件会保存对它的引用。

您必须确保取消注册不再使用的所有实例事件。

重要的是注册实例是IDisposable的情况,因为在处置实例时可能会触发事件。在这种情况下,我发现最容易让实例注册自己,并在Dispose中取消注册。

答案 1 :(得分:4)

事件的实施使得只要您的发布者处于活动状态,即使您没有对这些订阅者进行任何其他引用,所有订阅者也将保持活跃状态​​。

当然,这也意味着,如果您希望将订阅者独立于发布者进行清理,则必须分离订阅者。

答案 2 :(得分:3)

如果前一个实例仍处于活动状态,并且新实例也连接了一个事件处理程序,则该事件将触发两个处理程序(一次一个)。跟踪将事件处理程序附加到事件的时间非常重要,您还可以在不再需要它们时将它们分离。否则,旧实例将继续存在于内存中,执行可能导致意外结果的事件处理程序。

答案 3 :(得分:0)

您可以使用我的WeakEventHandler,基于WeakReference。由于它保留了对事件监听器的弱引用,因此它不会强制监听器生效。

see this answer