背景:
我试图问这个问题,但没有真正的结论,所以我想我会尝试以不同的方式问它,因为这个问题使我头疼。
我的应用程序是一种嵌入式HMI设计工具。这使用户(内部开发人员)能够在视觉上设计嵌入式HMI的外观,然后单击按钮生成C代码。现在大部分都可以工作。
该工具所做的主要事情之一是允许用户创建新的屏幕(然后可以在其上掉落控件)。在我的应用程序中,"屏幕"是一个对象。当添加新屏幕时,将其放置在List<Screen>
中,后来用于生成C代码。
该屏幕的属性之一是private Screen nextScreen
,它是对另一个屏幕对象的引用,该对象指示按下导航按钮时要显示的屏幕下一步显示。同样,这一切都很好。
问题:
但是,在使用该工具生成代码的工具时,我们发现了一个问题。创建了2个屏幕,第一个屏幕将其nextScreen
属性设置为第二个屏幕。稍后,决定第二个屏幕是错误的,因此已删除并创建了一个新的屏幕。但是,他们忘记将第一个屏幕nextScreen
属性设置为此新屏幕,因此它仍在引用原始屏幕,该屏幕在视觉上已删除。
生成代码时,结果C代码无法编译,因为第一个屏幕是引用一个屏幕,该屏幕在生成的C环境中不存在。
问题:
所以我的问题是我如何最好地实现一种删除方法,以确保引用"删除"对象知道并将该属性设置为null的任何内容?
到目前为止的想法:
1)我尝试创建" NextScreen"属性作为弱者,但这意味着每次删除完成时,我必须手动调用GC.Collect()...从我的理解中不理想!(我尝试此操作的示例可以在本文顶部的链接中找到)
2)我可以在删除后检查所有对象以引用被删除的对象并将其设置为null。但是,我上面描述的只是构成HMI的众多对象之一,其中大多数对其他对象都有一个或多个引用。所以这可能很慢,在我看来似乎不对。
3)也许使用IDISPOSABLE ???但是从我的理解来看,这是针对不受管理的代码!
我现在要阅读的任何想法或领域都会很棒,因为我现在将头发拉出来...不是我有很多!
我认为您可以使用ObjectPool模式创建和删除对象上的对象,并控制其livetime
-
让您的类包括一个字段,该字段指示它是否已无效,并且具有接收或遵循对类实例的参考的代码,请检查该字段以确保实例仍然有效。如果代码在一个实例中设置该字段,则对其的任何引用将不再是对有效实例的引用,而是(根据定义)成为无效实例的引用。
-
如果将
WeakReference
创建到对象上,则当GC检测到不存在对目标的非弱引用时,该WeakReference
的Target
属性将成为null
(如果复制对非NULL目标的引用是复制的对于另一个变量,即使弱参考是宇宙中唯一具有参考的宇宙中的东西,该变量也将保持目标。强迫完整的垃圾收集周期通常会立即使任何在任何地方都没有强烈引用但代表滥用GC系统的对象的任何弱参考。 -
实现一个"查找所有已使用的对象"例程,该例程计算了它已运行的次数,并且在每个类实例中都有一个字段,该例程将其计数器存储在其中。任何应视为"使用"的对象都将保持值"查找所有使用的对象"例程计数器上次运行时。这有点像GC对其所知道的对象所做的事情,但是如果您自己执行此操作,则可以决定哪种形式的参考形式应该证明有关对象的合理性。
您可以创建一个称为Deletable<T>
的新通用类来包装对象。它的工作原理类似于Nullable<T>
,因为它包含具有原始值的T
类型的属性。它需要一个可读取的bool
属性IsDeleted
,该属性指示是否已删除包装值,并且Delete
方法无需包装值,并设置IsDeleted
标志。
使用Screen
对象的所有内容都将切换到Deletable<Screen>
。删除屏幕时,请在包装器上调用Delete
。任何关心屏幕的代码都可以在使用scr.Value
之前检查scr.IsDeleted
。
这将允许垃圾收集清理任何大对象,同时在其位置留下一个不错的小"标志"值,您可以使用该值来检查是否已删除了真实对象。