SafeHandle类允许通过引用计数和来自P/Invoke封送处理程序的协作,安全地访问.NET下的本机资源,以避免过早地处理可能导致应用程序崩溃的句柄。
在某些情况下,通知垃圾收集器某些本机资源正在使用大量内存是有利的,例如,当所讨论的“句柄”是包装的本机库拥有的大型缓冲区时。GC.AddMemoryPressure可用于此目的;但是,必须在“句柄”的生存期结束时调用GC.RemoveMemoryPressure。
这两种方法似乎不兼容:SafeHandle是一个CriticalFinalizerObject,它的ReleaseHandle方法运行在一个受限的执行区域(CER)。由于GC.RemoveMemoryPressure没有ReliabilityContractAttribute,所以不能从CER调用它(我想在关键的终结时间,与内存压力有关的GC的某些部分可能不可用)。
我想到了两种方法,两种方法都很不雅致:
是否有一个共同的模式来创建一个具有相关内存压力的SafeHandle?
发布于 2016-08-03 21:34:58
它是一个很好的模式包装一个手柄,而不是暴露它在正常情况下。你可以像FileStream那样做那部分。据了解,句柄属于FileStream所有,关闭它是非法的。这不是强制的,但这是合同。
第二个问题是,您希望将SafeHandle的生存期绑定到它的包装器上。ConditionalWeakTable类允许您这样做。设计如下:
class Wrapper {
SafeHandle handle;
CWT cwt = new CWT() { { handle, this } };
~Wrapper() { RemoveMemoryPressure(); }
}如果句柄是活动的,则CWT使包装器保持活动。CWT用于将任意状态关联到不可扩展的对象,而不产生任何GC效果。
我不确定这一切是否值得,但这将是一个(大部分)满足您的需求的解决方案。
此外,我也不确定记忆压力在多大程度上有实际用途。
https://stackoverflow.com/questions/38753891
复制相似问题