该类SafeHandle
允许通过引用计数和 P/Invoke 编组器的合作安全访问 .NET 下的本机资源,以避免过早处理可能导致应用程序崩溃的句柄。
在某些情况下,通知垃圾收集器某些本机资源正在使用大量内存是有利的,例如,当所讨论的“句柄”是一个封装的本机库拥有的大缓冲区时。GC.AddMemoryPressure
可用于此目的;但是,GC.RemoveMemoryPressure
必须在“句柄”的生命周期结束时调用。
这两种方法似乎是不兼容的:SafeHandle
is aCriticalFinalizerObject
和它的ReleaseHandle
方法在受约束的执行区域 (CER) 中运行。与GC.RemoveMemoryPressure
noReliabilityContractAttribute
一样,不能从 CER 调用它(我猜在关键的完成时间,与内存压力有关的 GC 的某些部分可能不可用)。
我想到了两种方法,都非常不雅:
可以将 SafeHandle 包装到另一个对象中,该对象具有添加和删除内存压力的非关键终结器(和 Dispose 方法)。这有两个不足:首先,有人可以在不处理包装器的情况下处理 SafeHandle(它必须暴露才能传递给本地方法),因此内存压力被高估了。其次,当 SafeHandle 还活着时,包装器可能会变得未被引用,因此内存压力被低估了(可能更严重)。
SafeHandle 有一个管理内存压力的非关键可终结类型的字段。在这种情况下,上面的大多数问题都消失了,但是,句柄无法在其 Dispose 或 ReleaseHandle 方法中释放内存压力对象,因为这会导致 CER 中的 GC.RemoveMemoryPressure 调用。可以提供另一种方法(例如 DisposeNoncriticial),但是当句柄被强制转换为 IDisposable 或在 using 块中使用时,这会导致“切片”问题。
是否有创建具有相关内存压力的 SafeHandle 的通用模式?