我在4#之前使用C#3.5和C#版本支持TPL的反应式扩展。
我的应用程序在几个地方调用GC.Collect()(是的,我知道我不应该手动调用此方法,但请至少在这个问题上留下这一点)。在我实现多线程实现之前,它工作正常。在每个线程中调用GC.Collect(),以便在多线程上下文中调用它。
然后我使用Task实现多线程,我发现应用程序运行一段时间后内存使用量增加,线程停止正常工作。我从多核计算机上的CPU使用率下降到单线程级别而不是完全利用的情况下声明“线程停止正常工作”。
当我试图解决这个问题时,我唯一做的就是注释掉GC.Collect()调用,这个改变使线程正常工作。我想关闭GC.Collect(),除非我在我的应用程序中运行大的东西,没有GC.Collect(),我将遇到OutOfMemory异常。这就是我保持通话的原因。
现在有人可以解释为什么在使用高内存的机器上的多线程上下文中调用GC.Collect()会导致多线程问题吗?这个位有没有相关的理论?非常感谢您的回答。
答案 0 :(得分:11)
GC.Collect()
执行完整垃圾收集,该收集将阻止所有线程。它有一个重载GC.Collect(int)
,允许您指定要收集的世代。例如,GC.Collect(0)
只会收集第一代。不确定这会解决你的问题,但值得一试。
答案 1 :(得分:1)
正如Kirk所说,一个集合暂停所有线程。这可能会导致垃圾回收期间出现一些延迟。
如果您在多核计算机上运行应用程序,则可能需要尝试使用Server GC,确保app.config包含:
<configuration>
<runtime>
<gcServer enabled="true"/>
</runtime>
</configuration>
另外一个人可以启用并发GC(虽然我认为这是你的情况的默认值,例如多核机器上的桌面应用程序,运行.NET 3.5):
<configuration>
<runtime>
<gcConcurrent enabled="true" />
</runtime>
</configuration>
您可能会尝试使用ServerGC - 它也可能会暂停,但这些暂停可能会更短/更少,并且可能会提供更好的整体吞吐量。 您的里程可能会有所不同。