C# 显式移除事件处理程序

21 浏览
0 Comments

C# 显式移除事件处理程序

我想知道将一个对象设置为null是否会清除绑定到该对象事件的任何事件处理程序...\n例如:\n

Button button = new Button();
button.Click += new EventHandler(Button_Click);
button = null;
button = new Button();
button.Click += new EventHandler(Button_Click);
button = null;

\n等等...\n这会导致内存泄漏吗?

0
0 Comments

在C#中,当我们订阅了外部事件时,如果没有手动移除事件处理程序,那么对象将会一直存在,导致对象的生命周期比必要的时间长。这篇文章中给出了问题的解决方法。

根据文章中的讨论,结论是在事件到达类的外部时,应该从事件中移除委托。也就是说,当我们订阅外部事件时,应该在完成后取消订阅。否则,对象会比必要的时间长存在。

以下是解决方法的代码示例:

public class MyClass
{
    private ExternalClass externalObj;
    public MyClass()
    {
        externalObj = new ExternalClass();
        externalObj.ExternalEvent += HandleExternalEvent;
    }
    private void HandleExternalEvent(object sender, EventArgs e)
    {
        // 处理事件的代码
    }
    public void UnsubscribeFromExternalEvent()
    {
        externalObj.ExternalEvent -= HandleExternalEvent;
    }
}

在上面的代码中,我们创建了一个名为MyClass的类,该类订阅了一个来自ExternalClass的事件ExternalEvent。在MyClass的构造函数中,我们将HandleExternalEvent方法添加为事件处理程序。如果我们不手动移除事件处理程序,MyClass的实例将保持活动状态,直到ExternalClass的实例也被释放。

为了解决这个问题,我们定义了一个名为UnsubscribeFromExternalEvent的方法,在这个方法中,我们将HandleExternalEvent从ExternalEvent事件中移除。当我们完成使用MyClass的实例时,我们可以调用UnsubscribeFromExternalEvent方法来取消订阅外部事件。

通过这种方式,我们可以确保在不再需要事件处理程序时,及时从事件中移除委托,避免对象的生命周期比必要的时间长。这样可以提高内存的使用效率,并避免潜在的内存泄漏问题。

0
0 Comments

C#中显式删除事件处理程序的原因是:当事件源/发布者的生命周期很长而订阅者的生命周期较短时,如果事件源的寿命超过了订阅者,所有注册的订阅者都将被事件源保留“活跃”,即不会被垃圾回收器回收,除非他们取消订阅(并从事件发布者的通知列表中删除对自己的引用)。

解决方法是:在不再需要订阅事件时,要显式地取消订阅,以避免潜在的内存泄漏。可以通过使用“-=”操作符来取消订阅事件,将事件处理程序从事件的委托列表中移除。

示例代码如下:

// 定义一个事件
public event EventHandler MyEvent;
// 订阅事件
MyEvent += MyEventHandler;
// 取消订阅事件
MyEvent -= MyEventHandler;

需要注意的是,取消订阅事件时,应该使用相同的事件处理程序来移除订阅,否则订阅将无法成功取消。

此问题的解决方法已经在这个链接中得到了解答,并且有一个很好的标题和答案。因此,建议关闭此问题。

0
0 Comments

在这个例子中,如果button没有其他引用,那么在这里不需要移除事件处理程序以避免内存泄漏。事件处理程序是单向引用,所以只有在具有事件的对象生命周期很长,且希望避免处理程序(即具有处理程序方法的对象)的生命周期超过应有的时间时,才需要移除它们。在你的例子中,这种情况并不适用。

这是否意味着应用栏的事件处理程序也不需要明确删除(例如statechanged)?

这是一个相反的情况。AppBar是一个长寿的对象,而事件处理程序至少会使委托所引用的对象在AppBar存活期间一直存在,而你可能不希望发生这种情况。另一方面,如果处理程序是拥有该栏的窗口上的方法,那就无关紧要了。

0