使管理对象真正删除的

使管理对象真正删除的

问题描述:

背景:使管理对象真正删除的

我试着问this问题yesturday,但没有真正的结束,所以我想我会试着问它以不同的方式,因为这问题导致我大伤脑筋。

我的应用程序是嵌入式HMI设计工具。这允许用户(作为内部开发人员)以可视方式设计嵌入式HMI的外观,然后通过点击按钮生成C代码。现在大部分工作。

该工具的主要功能之一是允许用户创建新的屏幕(然后可以将控件放置在屏幕上)。在我的应用程序中,“屏幕”是一个对象。当添加新的屏幕时,它被放置在List<Screen>中,后者用于生成C代码。

该屏幕的其中一个属性是private Screen nextScreen,它是对另一个屏幕对象的引用,指示当按下导航按钮时下一个要显示的屏幕。这一切都很好。

问题:

然而,用工具打生成代码的时候,我们发现了一个问题。创建了2个屏幕,第一个屏幕的nextScreen属性设置为第二屏幕。稍后它决定第二个屏幕是错误的,所以它被删除并创建了一个新的屏幕。但是他们忘记将第一个屏幕nextScreen属性设置为这个新屏幕,所以它仍然引用了原始屏幕,该屏幕在视觉上已被删除。

生成代码时,生成的C代码无法编译,因为第一个屏幕引用了在生成的C环境中不存在的屏幕。

问:

所以我的问题是如何才能最好地实现删除的方式可确保任何引用被“删除”的对象知道它,并设置该属性为空?

思想至今:

1)我试图创造“nextScreen”属性作为其的WeakReference的工作,但它意味着我必须手动调用GC.Collect的()每次删除的时间完成...从我的理解不理想! (我试过这个的例子可以在本文顶部的链接中找到)

2)我可以在删除时检查所有对象的引用,并将其设置为空。但是我上面描述的只是组成HMI的许多对象之一,其中大部分对象都有一个或多个对其他对象的引用。所以这可能会很慢,在我看来这看起来不对。

3)也许使用IDisposable?但从我的理解,这是非托管代码!

任何想法或领域让我读起来会很好,因为我现在正在拉我的头发在这...不是我有很多!

我认为你可以使用ObjectPool的模式上的对象创建和删除的对象和一些包装,以控制其livetime

+0

感谢您对我所研究的建议,但是这并没有真正提供我需要的功能,如上所述。我一直在进行调查,得出的结论是,我的目的没有任何真正的事情,这真的让我很欣慰。因此,我现在正在实施我自己的经理类和支持界面,我将在完成后发布。 – TheGrovesy

其中GC的基本设计迫切需要的是,如果有任何方法,使代码可能遇到对象的引用时,该对象将继续存在。没有办法“删除”一个对象,因此对它的引用将会失效。有,但是,两件事情可以做:

  1. 有你的类包括指示是否已经无效,并具有接收或以下,以一个类实例的引用代码的字段,检查该字段确保实例仍然有效。如果代码在实例中设置该字段,则对该实例的任何引用将不再是对有效实例的引用,而是(根据定义)将成为对无效实例的引用。

  2. 如果您创建一个WeakReference到一个对象,那WeakReferenceTarget属性将成为null当GC检测出存在于目标没有非弱引用(如果一个非空对象的引用复制到另一个变量,即使弱参考是宇宙中唯一涉及目标的东西,该变量也会使目标保持活动状态)。强制执行一个完整的垃圾收集循环通常会立即使对任何在任何地方没有强烈引用的对象的弱引用立即失效,但会代表滥用GC系统的某些事情。

  3. 实现一个“查找所有使用的对象”例程,它计算它已经运行了多少次,并且每个类实例中都有一个字段,该例程将存储其计数器。任何应该被视为“使用”的对象都会保存上次运行时所用的“查找所有使用的对象”例程计数器的值。这有点像GC对它知道的对象所做的事情,但是如果你自己这样做,你可以决定哪些形式的引用应该将对象称为“被使用”。

+0

你可以扩展你的第三点多一点。这听起来很有趣,但我完全不知道它会如何工作。谢谢。 – TheGrovesy

+0

从概念上讲,想象每个对象都有一个“上次访问”字段,并且有一个进程“访问”它以某种方式可以找到的所有内容,并在每个遇到的对象中适当地更新字段。如果一个对象自从上次开始扫描以来没有被访问过,那么这意味着以这种方式执行的扫描不可能找到该对象。然而,使用上次访问的实际“挂钟”时间,要么需要存储足够多的无用的精度来区分其最后访问的对象... – supercat

+0

...在扫描开始之前与最后一次访问发生之前在扫描期间。用在每次扫描开始时递增的计数器替换时钟可以避免这个问题。 – supercat

你可以创建一个新的泛型类Deletable<T>来包装你的对象。它的工作原理类似于Nullable<T>,它包含一个保存原始值的T类型的属性。它需要一个只读的bool属性IsDeleted,它指示包装的值是否已被删除,以及Delete方法可以将包装值NULL并设置IsDeleted标志。

所有使用Screen对象的对象都将切换为Deletable<Screen>。当屏幕被删除时,请在包装上拨打Delete。如果屏幕被删除,任何关心的代码都可以在使用scr.Value之前检查scr.IsDeleted

这将允许垃圾收集来清理所有大对象,同时在它的位置留下一个很好的小“标记”值,您可以使用它来检查是否已删除实际对象。

+0

感谢您的意见。有趣的想法...我也不知道可空。尽管使用使用建议,你说它会允许垃圾收集器清理,但是这是真的吗?因为我猜可删除的对象仍然会持有对实际objetc的引用,所以不会收集到? – TheGrovesy

+0

其他对象只能包含对包装的引用。唯一对真实对象的引用是在包装中。当你在包装器上调用Delete时,它将清空唯一的引用,使其可用于垃圾收集。 –