首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带记忆压力的SafeHandle

带记忆压力的SafeHandle
EN

Stack Overflow用户
提问于 2016-08-03 21:24:04
回答 1查看 212关注 0票数 3

SafeHandle类允许通过引用计数和来自P/Invoke封送处理程序的协作,安全地访问.NET下的本机资源,以避免过早地处理可能导致应用程序崩溃的句柄。

在某些情况下,通知垃圾收集器某些本机资源正在使用大量内存是有利的,例如,当所讨论的“句柄”是包装的本机库拥有的大型缓冲区时。GC.AddMemoryPressure可用于此目的;但是,必须在“句柄”的生存期结束时调用GC.RemoveMemoryPressure

这两种方法似乎不兼容:SafeHandle是一个CriticalFinalizerObject,它的ReleaseHandle方法运行在一个受限的执行区域(CER)。由于GC.RemoveMemoryPressure没有ReliabilityContractAttribute,所以不能从CER调用它(我想在关键的终结时间,与内存压力有关的GC的某些部分可能不可用)。

我想到了两种方法,两种方法都很不雅致:

  1. 可以将SafeHandle包装到另一个具有非关键终结器(和Dispose方法)的对象中,该对象可以添加和消除内存压力。这有两个缺点:首先,有人可以在不处理包装器的情况下释放SafeHandle (必须将它公开以传递给本机方法),从而高估了内存压力。其次,当SafeHandle还活着时,包装器可能变得没有引用,因此内存压力被低估了(可能更严重)。
  2. SafeHandle有一个非关键的可终结类型的字段来管理内存压力.在这种情况下,上面的大多数问题都消失了,但是句柄不能在其dispose或ReleaseHandle方法中释放内存压力对象,因为这将导致CER中的GC.RemoveMemoryPressure调用。还可以提供另一种方法(如DisposeNoncriticial),但当句柄被转换到IDisposable或在使用块中使用时,这会导致“切片”问题。

是否有一个共同的模式来创建一个具有相关内存压力的SafeHandle?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-03 21:34:58

它是一个很好的模式包装一个手柄,而不是暴露它在正常情况下。你可以像FileStream那样做那部分。据了解,句柄属于FileStream所有,关闭它是非法的。这不是强制的,但这是合同。

第二个问题是,您希望将SafeHandle的生存期绑定到它的包装器上。ConditionalWeakTable类允许您这样做。设计如下:

代码语言:javascript
复制
class Wrapper {
 SafeHandle handle;
 CWT cwt = new CWT() { { handle, this } };

 ~Wrapper() { RemoveMemoryPressure(); }
}

如果句柄是活动的,则CWT使包装器保持活动。CWT用于将任意状态关联到不可扩展的对象,而不产生任何GC效果。

我不确定这一切是否值得,但这将是一个(大部分)满足您的需求的解决方案。

此外,我也不确定记忆压力在多大程度上有实际用途。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38753891

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档