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

时间:2022-07-02 03:44:27

In one class, ClassA, I have a timer object. In this class I register the event handlers for the timer elapsed event. In another class, ClassB, I have a public event-handler for the timer elapsed event. So I register the event-handler from ClassB in ClassA as follows:

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

myTimer.Elapsed += ClassBInstance.TimerElapsed

What happens if I were to create a new instance of ClassBInstance and the timer elapsed event fires when the previous instance of ClassB's event-handler is still tied to the Elapsed event of the timer?

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

For example:

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

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

4 个解决方案

#1


AFAIK, ClassBInstance is not garbage collected as long as there are events registered, because the event holds a reference to it.

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

You have to make sure that you unregister all events of instances that are no longer in use.

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

Important are cases where the registered instance is IDisposable, because the event could be fired when the instance is disposed. In this cases I found it easiest to let the instance register itself, and unregister in Dispose.

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

#2


Events are implemented such that as long as your publisher is alive all subscribers will be kept alive by the publisher even if you don't hold any other references to these.

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

Of course this also implies, that you must detach subscribers, if you want them to be cleaned-up independently of the publisher.

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

#3


If the previous instance is still alive, and the new instance has also hooked up an event handler, the event will trigger both handlers (one at a time). It's important to to keep track of when you attach event handlers to events, that you also detach them when they are no longer needed. Otherwise the old instances will continue to live in memory, executing event handlers that may lead to unexpected results.

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

#4


You could use my WeakEventHandler, based on WeakReference. Since it keeps a weak reference to the event listener, it doesn't force the listener to live.

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

see this answer

看到这个答案

#1


AFAIK, ClassBInstance is not garbage collected as long as there are events registered, because the event holds a reference to it.

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

You have to make sure that you unregister all events of instances that are no longer in use.

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

Important are cases where the registered instance is IDisposable, because the event could be fired when the instance is disposed. In this cases I found it easiest to let the instance register itself, and unregister in Dispose.

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

#2


Events are implemented such that as long as your publisher is alive all subscribers will be kept alive by the publisher even if you don't hold any other references to these.

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

Of course this also implies, that you must detach subscribers, if you want them to be cleaned-up independently of the publisher.

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

#3


If the previous instance is still alive, and the new instance has also hooked up an event handler, the event will trigger both handlers (one at a time). It's important to to keep track of when you attach event handlers to events, that you also detach them when they are no longer needed. Otherwise the old instances will continue to live in memory, executing event handlers that may lead to unexpected results.

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

#4


You could use my WeakEventHandler, based on WeakReference. Since it keeps a weak reference to the event listener, it doesn't force the listener to live.

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

see this answer

看到这个答案