【问题标题】:Should I call GC.Collect in custom thread pool?我应该在自定义线程池中调用 GC.Collect 吗?
【发布时间】:2010-12-16 03:52:36
【问题描述】:

我创建了有 5 个线程的线程池。当我的应用程序启动时,它们都会启动。问题是我在每个线程的线程循环回调函数中创建了这么多对象,并且应用程序运行时内存以秒为单位增加,这是线程循环回调函数:

void ThreadLoop(){
而(真){
var checkItems = _workItems.Where(w=>w.ActivedTime > 3).ToList();
foreach(检查项目中的变量 i){
_workItems[i.Id].ActivedTime = 0;
_workItems[i.Id].ExecutePostBack();
}
//重新创建新的_workItems字典
_workItems = _workItems.Where(w=>w.ActivedTime > 0).ToDictionary();
// 休眠线程以释放内存
Thread.Sleep(1000);
// 调用 Grab 收集器释放内存
       GC.Collect();
   }
}

我很困惑,在每个线程上调用 GC.Collect() 是好是坏?是否会导致性能不佳?

【问题讨论】:

    标签: asp.net asp.net-mvc asp.net-mvc-2 asp.net-ajax c#-3.0


    【解决方案1】:

    如果你必须问自己是否调用 GC.Collect,答案几乎肯定是“不”。 GC 旨在根据需要自动运行,并且自己调用它会说“我比 GC 本身更了解它应该何时运行”。任何不了解 GC 细节的人都更可能是错误的而不是正确的,并且实际上会使事情变得更糟。

    最好的做法几乎总是让 GC 自己处理。

    【讨论】:

    • 感谢您的建议。但是当我添加 GC.Collect() 时,当我在 2 小时内运行每个线程上有 1000 个工作项的线程池时,内存约为 100 mb。但是当我删除 GC.Collect() (让 .Net 为我收集)内存每秒增加并且很少减少时,在 2 小时内相同的工作项大约为 300~400 mb。 .Net 抓取收集器工作得更糟吗?如何让 .net 抓取收集器在我的情况下更好地工作?
    • GC 在需要的时候运行,也就是内存不足的时候。如果您有大量内存,则 GC 可能会在应用程序关闭之前不运行(如果有的话)。该应用程序似乎会稳定地使用更多内存。这并不意味着它运行得“更糟”——只是有一堆东西还不需要收集。
    • 无法等待关闭 App 释放内存,如何向 GC 提出我需要释放死亡对象并让 GC 更早、更安全地运行而不强制它立即收集?
    • 您有需要这样做的理由吗?最终,应用程序将需要比实际更多的内存,当它需要时,它将运行一个 GC 周期。如果你需要限制应用程序使用更少的内存,那么就这样做......但是强制 GC 运行,只是为了保持这个数字低,不会对你有任何好处——实际上可能会扰乱几代人并使当它自己运行时,它不能正常工作。让它发挥作用并相信它会起作用——在你可能遇到的每一种情况下,它都会好起来的。
    【解决方案2】:

    调用 GC.Collect 是不明智的,除非你真的需要,例如在某些与 COM 互操作的极端情况下。最好的情况是,您调用 GC 的次数超出了它的需要,最坏的情况是,您可能会将原本寿命较短的对象提升到更高的 GC 代中,这使得以后清理它们的成本更高。

    内存分配时内存压力触发GC,而不是时间。因此,如果您不再分配新对象,那么会经常看到内存中的临时峰值会持续很长时间。在这种情况下,调用 GC.Collect 可能没问题,但如果可以的话,我会避免在循环中调用它。

    【讨论】:

    • 我必须为你们发表同样的评论,伙计们。我还想听听您的意见:“当我添加 GC.Collect() 时,当我在 2 小时内运行每个线程上有 1000 个工作项的线程池时,内存约为 100 mb。但是当我删除 GC.Collect() (让.Net为我收集)内存每秒增加,很少减少,2小时内相同的工作项大约为300~400 mb。.Net抓取收集器工作得更糟吗?如何让.net抓取收集器更好地工作我的情况?”
    【解决方案3】:

    在大多数情况下,您不需要调用 GC.Collect(),除非在极少数情况下(我认为您的情况并非如此)。更多解释请看这里:http://blogs.msdn.com/b/ricom/archive/2004/11/29/271829.aspx

    【讨论】:

    • 感谢您的建议。但是当我添加 GC.Collect() 时,当我在 2 小时内运行每个线程上有 1000 个工作项的线程池时,内存约为 100 mb。但是当我删除 GC.Collect() (让 .Net 为我收集)内存每秒增加并且很少减少时,在 2 小时内相同的工作项大约为 300~400 mb。 .Net 抓取收集器工作得更糟吗?如何让 .net 抓取收集器在我的情况下更好地工作?
    • 如果您的性能测试结果并非如此,请务必执行您认为最好的方法。从长远来看,.NET VM 应该能够自我调整并表现得更好——这就是理论。
    • 嗯,我同意,我会在测试和测量后选择解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-25
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多