如何替换对 GC.Collect 的调用?

Posted

技术标签:

【中文标题】如何替换对 GC.Collect 的调用?【英文标题】:How can I replace this call to GC.Collect? 【发布时间】:2012-07-29 18:05:37 【问题描述】:

我有一个应用程序,它在伪代码中工作如下:

DisplayPrettyUI()
DoABunchOfReportingWorkThatAllocatesHundredsOfMB()
GC.Collect() //Free up the memory used in generating the report
DisplayReport()

现在,我无法完全摆脱 collect 调用,因为如果我这样做了,那么在生成报告后该进程会保留超过 GB 的内存,尽管应用程序仅托管 UI 组件来显示当时报告。同时,对 Collect 的调用似乎很“臭”;而且似乎必须有某种方法可以在不去那里的情况下处理这种情况。

可以去除这种气味吗? (我听说过像 AppDomain 之类的东西来解决这个问题,但我以前从未使用过 AppDomain,也不知道它对垃圾收集器有什么语义......)

【问题讨论】:

这听起来像是对GC.Collect的合法使用。 尝试优化 DoABunchOfReportingWorkThatAllocatesHundredsOfMB() 显然但除此之外没有很多其他选项 @EOG:这没有任何意义。 UI 中没有对报告基础架构数据的引用。垃圾收集器没有运行,因为这台机器有 12GB 的 RAM,因此它认为没有足够的内存压力来运行。空变量比无用更糟糕。 如果机器有12GB内存并且没有释放内存的压力,那你为什么觉得需要手动运行GC? 简单的家伙。你没有量化性能问题,所以我怎么知道重写是否有点激烈? 【参考方案1】:

您可以使用 Optimized 的 GCColletionMode 标志调用 GC.Collection,因此此时不一定会强制垃圾回收......如果没有必要,GC 可以延迟它。

http://msdn.microsoft.com/en-us/library/bb356724.aspx

另外看看AddMemoryPressure,这里有一些想法:

http://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure

【讨论】:

【参考方案2】:

我们通常解决此问题的方法是将报告拆分为单独的线程甚至物理进程,具体取决于我们使用的工具。

有些第三方报告工具是绝对的资源消耗者,当它们崩溃时往往会导致整个应用程序崩溃。将它们分离到自己的进程中可以隔离潜在的损害,并允许我们实例化足以使我们保持在资源限制之下,但仍能响应用户请求。

话虽如此,如果这不适合您的应用程序,我认为在您的情况下使用 Collect 没有任何问题。

【讨论】:

嗯……AppDomain 不是 .NET 领域的“进程”吗? 是的,但我们发现由于一些第三方工具是基于 COM 的,因此使用独立进程是最安全和最干净的。 那么 appdomain 有它自己的垃圾收集器“实例”吗? 没有。有关详细信息,请参阅此 SO 帖子:***.com/questions/2723579/…

以上是关于如何替换对 GC.Collect 的调用?的主要内容,如果未能解决你的问题,请参考以下文章

Dispose 中的 GC.Collect() 简单类

在python中使用gc.collect()清除内存对缓存数据的queue队列是否有影响

gc模块

unity中gc.collect和resources.unloadunusedassets功能有啥异同

跨 AppDomain 边界的垃圾收集对象

强制垃圾收集对活动对象以及长寿命对象有什么影响?