简体   繁体   English

C#中的GC.Collect和多线程

[英]GC.Collect and multithreading in C#

I am using C# 3.5 and the reactive extension supporting TPL in C# version before 4. 我正在使用C#3.5和4#之前在C#版本中支持TPL的反应式扩展。

My application calls GC.Collect() in several places (yes, I know that I should not manually call this method but please leave this point alone for at least this question). 我的应用程序在几个地方调用了GC.Collect()(是的,我知道我不应该手动调用这个方法,但请至少在这个问题上留下这一点)。 Before I put multithreading implementation in, it works fine. 在我实现多线程实现之前,它工作正常。 GC.Collect() is called in each of the thread so it is called in a multithreading context. 在每个线程中调用GC.Collect(),以便在多线程上下文中调用它。

Then I use the Task to implement multithreading and I found that after the application running for a while and the memory usage increases, the threads stop working properly. 然后我使用Task实现多线程,我发现在应用程序运行一段时间后内存使用量增加,线程停止正常工作。 I declare "the threads stop working properly" from the scenario that the CPU usage on a multi-core computer drops to single-thread level, rather than fully utilized. 我从多核计算机上的CPU使用率下降到单线程级别而不是完全利用的方案中声明“线程停止正常工作”。

When I attempted to tackle this problem, the only thing I did was to comment out the GC.Collect() call and this change makes the threads working fine. 当我试图解决这个问题时,我唯一做的就是注释掉GC.Collect()调用,这个改变使线程正常工作。 I would like to turn GC.Collect() off unless when I run something big in my application, without GC.Collect(), I will run into OutOfMemory exception. 我想关闭GC.Collect(),除非我在我的应用程序中运行大的东西,没有GC.Collect(),我将遇到OutOfMemory异常。 This is the reason I keep the call. 这就是我保持通话的原因。

Now could anyone explain why GC.Collect() being called in a multithreading context on a machine using high memory causes multithreading problem? 现在有人可以解释为什么在使用高内存的机器上的多线程上下文中调用GC.Collect()会导致多线程问题吗? Is there any related theory on this bit? 这个位有没有相关的理论? Thank you very much for the answer. 非常感谢您的回答。

GC.Collect() performs a full garbage collection which will block all threads. GC.Collect()执行完整的垃圾收集,它将阻止所有线程。 It has an overload GC.Collect(int) that allows you to specify which generations to collect. 它有一个重载GC.Collect(int) ,允许您指定要收集的代数。 For example, GC.Collect(0) will only collect the first generation. 例如, GC.Collect(0)将仅收集第一代。 Not certain that will solve your problem, but worth a shot. 不确定这会解决你的问题,但值得一试。

As Kirk has said, a collection pauses all threads. 正如Kirk所说,一个集合暂停所有线程。 This might result in some latency during garbage collection. 这可能会导致垃圾回收期间出现一些延迟。

If you are running your application on a multi-core machine, you might want to try using the Server GC, by making sure that your app.config contains: 如果您在多核计算机上运行应用程序,则可能需要尝试使用Server GC,确保app.config包含:

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

Also one can enable concurrent GC instead (though I think this is the default for your case, eg a desktop app on a multi-core machine, running .NET 3.5): 另外一个可以启用并发GC(虽然我认为这是你的情况的默认值,例如多核机器上的桌面应用程序,运行.NET 3.5):

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

You might try ServerGC - it might give pauses as well, but these pauses may be shorter/fewer and it might give a better overall throughput. 您可以尝试使用ServerGC - 它也可能会暂停,但这些暂停可能会更短/更少,并且可能会提供更好的整体吞吐量。 Your mileage may vary. 你的旅费可能会改变。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM