gpt4 book ai didi

.net - 为什么释放的 ArcObjects COM 对象在 GC 被手动强制完成之前没有完成?

转载 作者:行者123 更新时间:2023-12-02 05:28:07 24 4
gpt4 key购买 nike

我正在开发一个用于处理地理数据的 .NET 应用程序,该应用程序通过 ESRI 自己的 .NET 互操作程序集使用 ESRI 的 ArcObjects COM 库。

在生产环境中运行时,由于达到每个进程 2GB 的内存限制,进程可能会在某些操作期间崩溃。 (ArcObjects 是一个 32 位库。)这是因为某些处理步骤可以创建许多临时 ArcObjects 几何对象。尽管使用 FinalReleaseComObject 手动释放这些对象,它仍会泄漏内存并最终耗尽内存。和相关的辅助方法。但是,我可以通过调用 WaitForPendingFinalizers 强制 GC 释放内存。 ,并与 GC.CollectFinalReleaseComObject 一起定期调用它以控制内存使用。否则,许多对象将保留在内存中,直到进程退出(正常或异常)。

第一个问题:为什么ArcObjects COM 对象占用的内存没有立即释放?或者,为什么 GC 允许进程崩溃,而不是在崩溃前完成释放的 COM 对象并回收内存?

该应用程序在 Windows 2008 64 位生产环境中运行,而我使用 Windows 7 32 位进行开发。我可以让进程在生产箱上崩溃,但在我的开发箱上不会。我认为这可能是因为在本地我通常使用调试版本在 Visual Studio 中运行,但我也尝试过在没有调试器的情况下使用发布版本(不调试开始)但即使那样它也没有使用太多与生产中一样的内存,不会崩溃。

第二个问题:为什么?

编辑:在我之前的实验中,我发现 GC.Collect 本身是不够的,即使我明确地调用了它。我有一个实用程序方法,它调用 GC.Collect,然后调用 GC.WaitForPendingFinalizers,并在每次算法迭代后调用它以降低内存使用量。

最佳答案

托管应用程序中使用的 COM 对象位于运行时可调用包装器 (RCW) 的后面,它是一个托管对象,将 COM 对象的接口(interface)复制到托管客户端(它是托管组件和非托管组件之间的桥梁)。如果我没记错的话,实际的 COM 接口(interface)引用由 RCW 持有,而不是由您的代码持有。当您释放 COM 对象时,实际上是 RCW 被释放,但它本身是一个托管对象,在 GC 开始清理它之前不会消失。发生这种情况时,RCW 将被删除,对 COM 对象的最后引用也将消失,因此它可以自行销毁。 (根据文档,FinalReleaseComObject 应该将引用计数设置为 0,但我在过去看到过类似的行为,所以我怀疑文档是否正确。)

关于你的第二个问题,我有一个猜测:我在压力大的环境中看到,当系统负载很重时,GC 根本没有机会运行。当时我们确定 GC 在优先级较低的线程上运行,并且我们的应用程序使用了太多的 CPU,以至于 GC 永远没有机会清理。我们不得不添加另一个定期调用 GC.Collect() 的线程 - 这迫使 GC 线程唤醒并发挥其魔力。您可能正面临类似的情况。 (这也可能是您在 #1 中的问题背后的原因。)

关于.net - 为什么释放的 ArcObjects COM 对象在 GC 被手动强制完成之前没有完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12774236/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com