C# 垃圾收集会干扰对象创建吗?

C# 垃圾收集会干扰对象创建吗?,c#,wpf,garbage-collection,C#,Wpf,Garbage Collection,我正在开发一个WPF应用程序,其中包含一个DevExpress文档组,其中包含不同的面板和页面。我使用的一个名为“概述”的页面有一个非常大的图片(10.000 x 7.000)作为背景。当我点击按钮创建一个包含概览的新面板时,我可以在taskmanager中看到越来越多的内存被使用 在我关闭概览面板之后,内存使用率下降了一点,但从未像我打开页面之前那样低。如果我打开和关闭页面几次,内存使用就会达到一个临界点,程序就会冻结,永远不会加载概览。通过查看taskmanager,可以发现内存使用量大幅下

我正在开发一个WPF应用程序,其中包含一个DevExpress文档组,其中包含不同的面板和页面。我使用的一个名为“概述”的页面有一个非常大的图片(10.000 x 7.000)作为背景。当我点击按钮创建一个包含概览的新面板时,我可以在taskmanager中看到越来越多的内存被使用

在我关闭概览面板之后,内存使用率下降了一点,但从未像我打开页面之前那样低。如果我打开和关闭页面几次,内存使用就会达到一个临界点,程序就会冻结,永远不会加载概览。通过查看taskmanager,可以发现内存使用量大幅下降

垃圾收集器不应该在我关闭后立即删除我的概述的实例,从而删除对我的概述的所有引用吗?垃圾收集器在创建新的概览页面的过程中决定“收集”,因此中断创建吗?p> 通过读取,它显示以下内容:

当下列条件之一为真时,会发生垃圾回收:

  • 系统的物理内存不足
  • 所使用的内存 托管堆上分配的对象超过了可接受的 门槛。随着过程的进行,该阈值不断调整 跑步
  • 调用GC.Collect方法。几乎在所有情况下,你都是这样 不必调用此方法,因为垃圾收集器正在运行 连续不断地。此方法主要用于特殊情况和 测试

因此,它不会像您预期的那样,在关闭概览后立即清除内存。GC会在需要时清除内存。

这一部分是什么让你心烦

通常,大型对象堆不会被压缩,因为复制 大型对象会造成性能损失。然而,从 在.NET Framework 4.5.1中,您可以使用
GCSettings.LargeObjectHeapCompactionMode
属性压缩大型 对象按需堆

因此,您的映像将立即升级到Gen 2对象池,而且还会添加到大型对象堆中。当收集器在工作站模式下运行(Windows 7、8等计算机的默认模式,Windows server版本的服务器)时,将永远不会收集或压缩这些对象。
我很确定强制执行一个
GC.Collect()
对您来说绝对没有任何作用,因为收集器(在工作站模式下)将忽略大型对象堆

我曾在Windows7机器上测试过一个繁重的消息处理服务,在发送了10万条消息后,应用程序将以内存不足异常终止将收集器切换到服务器模式为我解决了这个问题。

从MSDN条目:-将其添加到项目的app.config文件中

<configuration>
   <runtime>
      <gcServer enabled="true"/>
   </runtime>
</configuration>

更新
好的,删除终结器,这不是它的用途,它对垃圾收集没有影响或是负面影响

调用CG.Collect()并不能保证内存使用率会下降,收集器是一个复杂的野兽,预测它在任何给定情况下会做什么是一件愚蠢的差事

在这个阶段,你几乎只能做两件事,你可能需要同时做这两件事

  • 确保没有对大型对象的引用,包括 侦听该对象引发的事件的事件处理程序

  • 通过内存分析器运行它,就像上面评论中提到的ANTS一样


  • 哪个版本的.net?在我关闭概览面板后,内存使用率下降了一点,但从未像我打开页面前那样低-这是正常的行为,因为垃圾收集器不会在关闭面板后立即收集内存。你确定没有更多的参考文献可以阻止GC收集你的概述吗?可以使用一些内存分析器来验证它。@BinaryWorrier我正在使用.NET4。0@AndyKorneyev你能给我推荐一个可以用来检查的内存分析器吗?@AndyKorneyev在考虑过之后;假定收集的“垃圾”之后释放的内存不是收集器释放内存的标志吗?应用程序仍在运行,不会抛出任何异常。是的,这可能是第一点。这仍然是我的第二个问题。垃圾收集器可能是我的应用程序不加载概览而冻结的原因吗?如果您正在创建概览的新实例,我看不出GC清除旧实例时会出现任何中断。但我可能错了。我添加了你的代码,但不幸的是,我得到了相同的结果。这适用于.Net 4.0还是仅适用于.Net 4.5.1?我还将'GC.Collect()'添加到overview close函数中,但这也没有帮助。让我困惑的是,我没有得到任何类型的异常,应用程序只是冻结。我确保通过使用IsServerGC()激活servermode垃圾收集器,它返回true。如果我理解正确,现在我应该能够使用GC.Collect()手动调用GC,这也会影响大型对象堆。调用Collect()时,不会释放内存。这是否表明仍有对我的概述的引用隐藏在何处,因此垃圾收集器不会释放内存?我甚至在overview类中添加了一个析构函数来设置image.Source=null。我尝试删除所有事件处理程序,但没有改变任何事情(也许我没有得到所有的事件处理程序?)。但是,在您告诉我析构函数无法工作后,我添加了一个按钮(我们称之为“b1”),用于设置image.Source=null。如果我在点击“b1”后调用GC,内存实际上是被释放的。奇怪的是,如果我调用与b1相同的代码