【问题标题】:GC does not collect object that implements interface from interop assembly, no rootsGC不从互操作程序集中收集实现接口的对象,没有根
【发布时间】:2011-12-19 13:24:10
【问题描述】:

经过几分钟的工作,托管内存包含大量未引用的对象,这些对象是通过从互操作程序集实现接口创建的。 GC.Collect 不会从内存中删除对象。

看起来 .NET 为 .NET 对象创建了 COM 可调用包装器,并且包装器以某种方式保存了对对象的引用。但是如何调查呢?

调查:

0:016> !dumpheap -stat 将堆对象加载到我们的缓存中。 共有 905,554 个对象 统计数据: MT Count TotalSize 更改类名称 ... 0x05127ac0 796 9,552 796 Application.GenericListener ... 总共 905,554 个对象,总大小:77,354,192

类型定义如下:

// C#代码: 公共类 GenericListener: OurEventListener, IDisposable { ... } // GenericListener 没有终结器 公共抽象类 OurEventListener : EventListener { ... } //互操作程序集: [指导(“...”)] [类型库类型(256)] [接口类型(1)] 公共接口 IListener { ... }

类型使用如下:

var listener = new GenericListener(); 我们的ComObject.Subscribe(listener); ... 我们的ComObject.Unsubscribe(监听器); listener.Dispose();

对象:

0:016> !dumpheap -mt 0x05127ac0 将堆对象加载到我们的缓存中。 地址 MT 大小 027a11d4 05127ac0 12 2 Application.GenericListener 0326d354 05127ac0 12 2 Application.GenericListener 09c5812c 05127ac0 12 2 Application.GenericListener 09c83000 05127ac0 12 2 Application.GenericListener ...

对象是根:

0:016> !gcroot 027a11d4 注意:在堆栈上找到的根可能是误报。运行“!help gcroot” 更多信息。 扫描线程 0 OSThread 1444 扫描线程 2 OSThread b40 扫描线程 7 OSThread 1630 扫描线程 8 OSThread a8 扫描线程 13 OSThread 1328 域(005F2E30):句柄(RefCnt):182d48:根:027a11d4(Application.GenericListener)

有什么想法吗?

更新:添加监听器的使用方式。

【问题讨论】:

  • 您自己不处理该对象是有原因的吗?您几乎无法控制垃圾收集器,并且您所做的任何控制都会以性能为代价。你发布的代码很少,我要客串了,gc 无法收集它的资源,因为它正在处理代码。
  • 您在使用 CLR 托管吗?我的意思是您是否将托管代码加载到非托管进程中?
  • @Ramhound Dispose 为所有这些对象调用。无论如何,终结器没有在 GenericListener 中定义,因此 GC 应该在对象未引用时将其删除。但事实并非如此。
  • @Aliostad GenericListener 被传递给 COM 对象,但它在同一个进程中。

标签: c# com interop garbage-collection


【解决方案1】:

这是您在 C# 中使用的 COM 对象吗?检查您是否已根据需要调用FinalReleaseComObjectReleaseCOMObject,以释放RCW。

【讨论】:

  • GenericListener 被传递给 COM 对象以订阅其事件。所有留在内存中的听众都被取消订阅。
猜你喜欢
  • 1970-01-01
  • 2014-08-17
  • 2018-03-20
  • 2013-04-25
  • 1970-01-01
  • 2012-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多