我是否需要在对象被孤立之前从对象中删除事件订阅?

Do I need to remove event subscriptions from objects before they are orphaned?(我是否需要在对象被孤立之前从对象中删除事件订阅?)
本文介绍了我是否需要在对象被孤立之前从对象中删除事件订阅?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我的软件有两个对象实例,其中一个订阅了另一个的事件.我是否需要在它们成为孤儿之前相互取消订阅,以便垃圾收集器清理它们?或者还有什么其他原因我应该清除事件关系?如果订阅的对象是孤立的,但订阅者不是,反之亦然?

If my software has two object instances, one of which is subscribed to the events of the other. Do I need to unsubscribe them from one another before they are orphaned for them to be cleaned up by the garbage collector? Or is there any other reason why I should clear the event relationships? What if the subscribed to object is orphaned but the subscriber is not, or vise versa?

推荐答案

是的.事件发布者持有对对象的引用,并且会阻止它们被垃圾回收.

Yes you do. The event publishers are holding references to the objects, and would prevent them from being garbage collected.

让我们看一个例子来看看会发生什么.我们有两个班级;一个暴露事件,另一个消耗它:

Let's look at an example to see what happens. We have two classes; one exposes an event, the other consumes it:

class ClassA
{
    public event EventHandler Test;
    ~ClassA()
    {
        Console.WriteLine("A being collected");
    }
}
class ClassB
{
    public ClassB(ClassA instance)
    {
        instance.Test += new EventHandler(instance_Test);
    }

    ~ClassB()
    {
        Console.WriteLine("B being collected");
    }

    void instance_Test(object sender, EventArgs e)
    {
        // this space is intentionally left blank
    }
}

注意 ClassB 如何不存储对 ClassA 实例的引用;它只是连接了一个事件处理程序.

Note how ClassB does not store a reference to the ClassA instance; it merely hooks up an event handler.

现在,让我们看看如何收集对象.场景一:

Now, let's see how the objects are collected. Scenario 1:

ClassB temp = new ClassB(new ClassA());
Console.WriteLine("Collect 1");
GC.Collect();
Console.ReadKey();
temp = null;
Console.WriteLine("Collect 2");
GC.Collect();
Console.ReadKey();

我们创建一个 ClassB 实例并通过 temp 变量保存对它的引用.它传递了一个 ClassA 的新实例,我们不会在任何地方存储对它的引用,因此它在 ClassB 构造函数完成后立即超出范围.我们让垃圾收集器在 ClassA 超出范围时运行一次,在 ClassB 超出范围时运行一次.输出:

We create a ClassB instance and hold a reference to it through the temp variable. It gets passed a new instance of ClassA, where we do not store a reference to it anywhere, so it goes out of scope immediately after the ClassB constructor is done. We have the garbage collector run once when ClassA has gone out of scope, and once when ClassB as gone out of scope. The output:

Collect 1
A being collected
Collect 2
B being collected

场景 2:

ClassA temp = new ClassA();
ClassB temp2 = new ClassB(temp);
temp2 = null;
Console.WriteLine("Collect 1");
GC.Collect();
Console.ReadKey();
temp = null;
Console.WriteLine("Collect 2");
GC.Collect();
Console.ReadKey();

创建了一个新的 ClassA 实例,并且对它的引用存储在 temp 变量中.然后创建一个新的 ClassB 实例,将 temp 中的 ClassA 实例传递给它,并将对它的引用存储在 temp2 中.然后我们将 temp2 设置为 null,使 ClassB 实例超出范围.和以前一样,我们让垃圾收集器在每个实例超出范围后运行.输出:

A new instance of ClassA is created and a reference to it is stored in the temp variable. Then a new instance of ClassB is created, getting the ClassA instance in temp passed to it, and we store a reference to it in temp2. Then we set temp2 to null, making the ClassB instance going out of scope. As before, we have the garbage collector run after each instance has gone out of scope. The output:

Collect 1
Collect 2
B being collected
A being collected

所以,总结一下;如果暴露事件的实例超出范围,则无论是否连接了事件处理程序,它都可用于垃圾收集.如果一个实例的事件处理程序连接到另一个实例中的事件,则在分离事件处理程序或附加事件处理程序的实例可用于垃圾收集之前,它将无法用于垃圾收集.

So, to conclude; if the instance that exposes an event goes out of scope, it becomes available for garbage collection, regardless of whether there are event handlers hooked up or not. If an instance that has an event handler hooked up to an event in another instance, it will not be available for garbage collection until either the event handler is detached, or the instance to which the event handler is attached becomes available for garbage collection.

这篇关于我是否需要在对象被孤立之前从对象中删除事件订阅?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)