Vok*_*erg 14 c# clr memory-management
我的.NET Windows服务应用程序中存在内存泄漏问题.所以我开始阅读有关.NET内存管理的文章.我在Jeffrey Richter的一篇文章中找到了一个有趣的练习.这个练习名称是"对象复活".它看起来像是将全局或静态变量初始化为"this"的位置代码:
protected override void Finalize() {
Application.ObjHolder = this;
GC.ReRegisterForFinalize(this);
}
Run Code Online (Sandbox Code Playgroud)
我知道这是一个不好的做法,但我想知道使用这种做法的模式.如果你知道,请写在这里.
来自同一篇文章:"复活的好用途很少,如果可能,你真的应该避免它."
我能想到的最佳用途是"回收"模式.考虑一个生产昂贵的,几乎不可改变的物体的工厂; 例如,通过解析数据文件,或通过反映程序集或深度复制"主"对象图来实例化的对象.每次执行这个昂贵的过程时,结果都不太可能改变.从头开始避免实例化符合您的最佳利益; 但是,由于某些设计原因,系统必须能够创建许多实例(没有单例),并且您的消费者无法了解工厂,以便他们可以"返回"对象本身; 他们可能会注入对象,或者获得一个工厂方法委托,从中获取引用.当依赖类超出范围时,通常也是实例.
一个可能的答案是覆盖Finalize(),清理实例的任何可变状态部分,然后只要Factory在范围内,就将实例重新附加到Factory的某个成员.这允许垃圾收集过程实际上"回收"这些对象的有价值部分,否则它们将超出范围并被完全破坏.工厂可以查看它的"垃圾箱"中是否有可用的回收物品,如果可以,它可以将其抛光并将其移出.如果进程使用的总对象数增加,则工厂只需要实例化对象的新副本.
其他可能的用途可能包括一些高度专业化的记录器或审计实现,您希望在其死后处理的对象将自己附加到由此过程管理的工作队列.在该过程处理它们之后,它们可以完全被破坏.
一般来说,如果你想要家属思考他们是摆脱一个对象,或者不必打扰,但你想保留实例,复活可能是一个很好的工具,但你必须仔细观察它避免接收复活的引用的对象变成"打包鼠"的情况,并保留在进程的生命周期内在内存中创建的每个实例.
我的一个兄弟曾经在高性能仿真平台上工作过。他向我讲述了在应用程序中,对象构造如何成为应用程序性能的明显瓶颈。这些对象似乎很大并且需要一些重要的处理才能初始化。
他们实现了一个对象存储库来包含“退休”的对象实例。在构造新对象之前,他们首先检查存储库中是否已存在该对象。
权衡是增加内存消耗(因为一次可能存在许多未使用的对象)以提高性能(因为对象构造的总数减少)。
请注意,实施此模式的决定是基于他们在特定场景中通过分析观察到的瓶颈。我预计这是一个特殊情况。