在几分钟的工作之后,托管内存包含许多通过实现interop程序集的接口创建的类型的未引用对象。 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)
有什么想法吗?
更新:添加监听器的使用方式。