【问题标题】:GC.Collect and multithreading in C#GC.Collect 和 C# 中的多线程
【发布时间】:2010-09-17 01:14:58
【问题描述】:

我正在使用 C# 3.5 和在 C# 4 之前的版本中支持 TPL 的响应式扩展。

我的应用程序在多个地方调用了 GC.Collect()(是的,我知道我不应该手动调用此方法,但请至少在这个问题上保留这一点)。在我放入多线程实现之前,它工作正常。 GC.Collect() 在每个线程中被调用,所以它在多线程上下文中被调用。

然后我使用Task实现多线程,发现应用运行一段时间后,内存使用量增加,线程停止正常工作。我从多核计算机上的 CPU 使用率下降到单线程级别而不是完全利用的情况下声明“线程停止正常工作”。

当我试图解决这个问题时,我所做的唯一一件事就是注释掉 GC.Collect() 调用,这个更改使线程工作正常。我想关闭 GC.Collect(),除非当我在我的应用程序中运行一些大的东西时,如果没有 GC.Collect(),我会遇到 OutOfMemory 异常。这就是我保持通话的原因。

现在谁能解释为什么在使用高内存的机器上的多线程上下文中调用 GC.Collect() 会导致多线程问题?有没有关于这个位的相关理论?非常感谢您的回答。

【问题讨论】:

    标签: c# multithreading


    【解决方案1】:

    GC.Collect() 执行 full 垃圾回收,这将阻塞所有线程。它有一个重载GC.Collect(int),允许您指定要收集的世代。例如,GC.Collect(0) 只会收集第一代。不确定这是否能解决您的问题,但值得一试。

    【讨论】:

    • 多么快速而有见地的帮助。我会试一试。非常感谢。
    【解决方案2】:

    正如Kirk 所说,集合会暂停所有线程。这可能会导致垃圾收集过程中出现一些延迟。

    如果您在多核机器上运行应用程序,您可能想尝试使用服务器 GC,方法是确保您的 app.config 包含:

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

    也可以改为启用并发 GC(尽管我认为这是您的情况的默认设置,例如运行 .NET 3.5 的多核机器上的桌面应用程序):

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

    您可以尝试使用 ServerGC - 它也可能会产生暂停,但这些暂停可能会更短/更少,并且可能会提供更好的整体吞吐量。 您的里程可能会有所不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-19
      • 2012-05-11
      • 2013-03-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多