C# 在终结器中枚举列表

C# 在终结器中枚举列表,c#,finalizer,C#,Finalizer,我有一个类,它保存着非托管资源的列表。这些应该在终结器中清理,以确保没有泄漏。但是,它们包含在列表中。对于这种情况,我有几个问题: 我假设在列表中列举列表是不安全的,对吗 终结器,因为列表可能已被删除 垃圾收集 是将每个单独的资源封装在实现终结器的类中的唯一其他方法,从而给垃圾收集器增加更大的压力吗?然后列表将存储这个类 关于最终确定指南的简要说明 对象的Finalize方法应释放所有 对象拥有。此外,Finalize方法应仅发布 对象持有的资源。最终确定方法应该是 不引用任何其他对象 最终

我有一个类,它保存着非托管资源的列表。这些应该在终结器中清理,以确保没有泄漏。但是,它们包含在
列表中。
对于这种情况,我有几个问题:

  • 我假设在列表中列举列表是不安全的,对吗 终结器,因为列表可能已被删除 垃圾收集
  • 是将每个单独的资源封装在实现终结器的类中的唯一其他方法,从而给垃圾收集器增加更大的压力吗?然后列表将存储这个类

关于最终确定指南的简要说明

对象的Finalize方法应释放所有 对象拥有。此外,Finalize方法应仅发布 对象持有的资源。最终确定方法应该是 不引用任何其他对象

最终确定和处置指南位于文章底部

我在这里找到了答案: . 此处supercat声明:

如果一个对象有一个活动的终结器,那么如果GC将收集它(但对于终结器的存在),GC将把它添加到一个对象队列中,该队列中的终结器应该尽快运行,并在完成后取消激活它。队列中的引用将阻止GC在终结器运行之前收集对象;一旦终结器完成,如果不存在对该对象的其他引用,并且该对象尚未重新注册其终结器,则该终结器将停止存在


因此,在终结队列中,对象被认为是可访问的,这意味着内部列表也被认为是可访问的。因此,从终结器访问列表是安全的。

考虑使用
SafeHandle
。似乎有专门用于此目的的类。否<代码>安全缓冲区在这里没有帮助。列表包含的INTPTR是指向Marshal.AllocHGlobal分配的非托管内存的指针。创建一个派生的SafeBuffer类,该类使用Marshal.AllocHGlobal进行分配,使用Marshal.FreeHGlobal进行释放,然后将这些实例存储在列表中,这样可以解决问题。是;导出它会有帮助。这意味着如果我需要分配数千个非托管内存的小部分,唯一的方法就是给垃圾收集器施加巨大的压力,让数千个对象带有终结器?@Janiles我不相信它会这样做,我主要想指出,在终结器中创建对象可能会防止对象被垃圾收集。但是,如果创建对象所拥有的分配/指针列表,则需要实现IDisposable模式,以便dispose方法按照垃圾收集器和框架所期望的模式处理托管和非托管资源“应仅释放对象持有的资源”-这是否包括其他对象,或者这些对象不被视为资源?如果不包括,则后者“finalize方法不应引用任何其他对象”“适用,我不应该引用终结器中的列表。@Brad Abrams和Krzystof Cwalina的Janiles框架设计指南也建议尽可能使用SafeHandle来管理资源。。。。第9.4.2节(第329页)有一些很好的信息…@Janiles我相信它主要是指该对象负责创建的对象。换句话说,如果您的对象没有在内存中创建分配,那么对象取消分配它将不是一个好主意,因为它可能正在被另一个对象使用。