说我有
var hGCFile = GCHandle.Alloc(buffer, GCHandleType.Pinned)
我P /用
调用一些非托管函数SaveStream(hGCFile.AddrOfPinnedObject())
此外,假设上述函数保存缓冲区地址并在整个应用程序的生命周期中使用它。
在这种情况下,调用
是否有好处hGCFile.Free()
在关闭我的申请之前?只是我猜想CLR会在appdomain拆解后无论如何都会这样做
答案 0 :(得分:3)
嗯,缓冲区的终结器永远不会运行。很难看出这可能是多么重要,如果它是一个里面有任何有趣内容的物体,你将无法固定它。
非常对垃圾收集器不友好,它必须不断地解决障碍,并且不能很好地压缩堆,以便为您的应用程序提供最佳的CPU缓存使用。特别糟糕的是如果它在第0代,那就是。
很少有理由给GC带来如此艰难的时间,只需分配真正的不可移动的内存。使用Marshal.AllocCoTaskMem()和Marshal.StructureToPtr()(如果需要的话)。现在你做关心在卸载AppDomain时释放那个内存也不会终止进程。那个IntPtr将是奇闻趣事。
但是请注意,AppDomain的生命周期不以任何方式与非托管代码的生命周期相关联。您加载的DLL不会与AppDomain一起卸载。从您的问题不清楚这个非托管代码是否仍然可以使用该缓冲区,因为它仍然存在。如果确实如此,那么确实重要的是你不使用固定内存。
答案 1 :(得分:2)
卸载AppDomain
后,保证释放AppDomain
分配的所有内存。
几天前读到他们实际上在创建AppDomain
之前和卸载之后将内存消耗减少到12个字节。)。
答案 2 :(得分:0)
退出应用程序后,您需要确保释放所有非托管资源。 GCHandle
处理托管资源(CLR堆),因此无需执行任何操作。
不释放固定GCHandle
将导致GC无法移动对象并压缩堆中已用内存。所以这将是所有托管内存,如果应用程序退出,它就不再重要了。