c# - GC 不收集实现互操作程序集接口(interface)的对象,没有根

标签 c# com interop garbage-collection

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

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

调查:

0:016> !dumpheap -stat
Loading the heap objects into our cache.
total 905,554 objects
Statistics:
        MT    Count    TotalSize       Change Class Name
...
0x05127ac0      796        9,552          796 Application.GenericListener
...
Total 905,554 objects, Total size: 77,354,192

类型定义如下:

// C# code:
public class GenericListener: OurEventListener, IDisposable { ... }
// GenericListener does NOT have finalizer
public abstract class OurEventListener : EventListener { ... }

//Interop assembly:
[Guid("...")]
[TypeLibType(256)]
[InterfaceType(1)]
public interface IListener { ... }

类型使用如下:

var listener = new GenericListener();
ourComObject.Subscribe(listener);
...
ourComObject.Unsubscribe(listener);
listener.Dispose();

对象:

0:016> !dumpheap -mt 0x05127ac0
Loading the heap objects into our cache.
 Address       MT     Size
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
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 0 OSThread 1444
Scan Thread 2 OSThread b40
Scan Thread 7 OSThread 1630
Scan Thread 8 OSThread a8
Scan Thread 13 OSThread 1328
DOMAIN(005F2E30):HANDLE(RefCnt):182d48:Root:  027a11d4(Application.GenericListener)

有什么想法吗?

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

最佳答案

这是您在 C# 中使用的 COM 对象吗?检查您是否调用过FinalReleaseComObjectReleaseCOMObject如果需要的话,释放 RCW。

关于c# - GC 不收集实现互操作程序集接口(interface)的对象,没有根,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7967969/

相关文章:

c# - 如何将 Silverlight 应用程序放入 ASP MVC View 页面?

c# - 代码契约(Contract)的好处

c++ - 无注册 COM 进程外 EXE

interop - 在Clojure中动态访问Java字段?

c# - 如何从访问托管代码的 native 线程强制使用正确的 AppDomain?

c# - 获取传递给子模块 (C#.NET dll) 内的主模块 (VC++ exe) 的参数

c# - 如何在 C# 中使用的以 C++ 编写的外部 .dll 资源上正确创建入口点

c# - 服务器上的日期格式不同

python - 以编程方式取消保护 Excel 文件

C# 在 Excel 进程被破坏的情况下关闭多个 Excel 对象的正确方法