【问题标题】:How to force garbage collector to run?如何强制垃圾收集器运行?
【发布时间】:2011-05-14 12:43:25
【问题描述】:

今天面试官问我这个……有答案吗?

【问题讨论】:

  • 这个问题有很好的信息说明为什么你不应该这样做:stackoverflow.com/questions/118633/…
  • 你为什么这样说
  • @Jason - 也许面试官不想听到解决方案,而是想了解 Andrew 的知识和反对这样做的理由,然后这个问题才有意义。
  • @martinstoeckli 这仍然是一个可怕的问题。在压力大的面试中掌握知识的人不会意识到这是一个技巧问题,或者想提供额外的信息。那么这个问题并不能帮助面试官区分有知识的人还是没有知识的人。所以这个问题还是很可怕的。
  • "什么时候强制垃圾回收?"对我来说听起来像是一个很好的面试问题(“如何”:不是那么多)。初学者:我不知道。中级:从不。专家:当你写一个内存泄漏测试时。

标签: c#


【解决方案1】:

【讨论】:

    【解决方案2】:
    GC.Collect() 
    

    来自MDSN

    使用此方法尝试回收所有 无法访问的内存。

    所有对象,无论多长时间 他们一直在记忆中,是 考虑收集;然而, 在托管中引用的对象 不收集代码。用这个 强制系统尝试的方法 回收最大数量 可用内存。

    【讨论】:

      【解决方案3】:

      GC.Collect();

      但请记住,垃圾收集器可能不会总是清理您所期望的...

      【讨论】:

      • 你这是什么意思?它可以意外清理什么?
      • @Voldemort - 它不会意外清理任何东西。但它可能无法清理您期望的所有内容。
      【解决方案4】:

      不建议显式调用gc,但如果调用

      GC.Collect();
      GC.WaitForPendingFinalizers();
      

      它会在整个代码中显式调用 GC,不要忘记在 GC.Collect() 之后调用 GC.WaitForPendingFinalizers();

      【讨论】:

      • WaitForPendingFinalizers 不一定会提供“更好的性能”:它只是阻塞,直到完成队列中的所有对象都已完成(您之前调用 Collect 时可能已将这些对象放在那里) )。如果您希望有机会收集这些对象,那么您需要另一个调用Collect 调用WaitForPendingFinalizers
      • 由于调用 gc.Collect 的少数几个好理由之一是作为释放未正确处理的资源的最后努力,WaitForPendingFinalizers 似乎是必要的步骤。不过,不确定在这种情况下避免过度调用 gc.Collect 的最佳做法是什么。顺便说一句,我想知道 gc.Collect “必须”促进几代人是否有任何技术原因?除非有足够的东西被分配到一个人身上来证明推进它的合理性,否则让几代人留在原地似乎更有用。
      • C# 初学者注意事项(像我一样):GC 强制调用不能保证,一些具体未使用的对象会从内存中删除。 (一种方法是使用“使用语句”(msdn.microsoft.com/ru-ru/library/yh598w02(v=vs.80).aspx))
      • 为什么打电话给WaitForPendingFinalizers很重要?
      【解决方案5】:

      您不想强制垃圾收集器运行。

      但是,如果您曾经这样做过(当然,作为纯粹的学术练习):

      GC.Collect()
      

      【讨论】:

      • 我更喜欢@Karthik 的回答,在某些情况下应用程序应该合法地调用 GC.Collect()。不过很少见。
      • 假设您有一组弱引用,并想检查是否存在任何“实时”引用。在检查之前调用 GC.Collect() 是有意义的。只是说。
      • 投反对票,因为开场白实际上不正确;是的,我确实想强制垃圾收集器运行。
      【解决方案6】:

      System.GC.Collect() 强制垃圾收集器运行。不建议这样做,但可以在出现情况时使用。

      【讨论】:

      • 为什么不推荐?
      • GC.Collect() 运行起来很昂贵。做超过必要的事情是不可取的。什么时候应该调用它的代码写得很好。您通常应该只在专门的边缘情况下自行收集。 stackoverflow.com/a/21961777/2710988
      【解决方案7】:

      我认为 .Net Framework 会自动执行此操作,但以防万一。 首先,确保选择要擦除的内容,然后调用垃圾收集器:

      randomClass object1 = new randomClass
      ...
      ...
      // Give a null value to the code you want to delete
      object1 = null;
      // Then call the garbage collector to erase what you gave the null value
      GC.Collect();
      

      我想就是这样。希望我能帮助别人。

      【讨论】:

        【解决方案8】:

        由于我的声誉太低而无法发表评论,因此我会将其发布为答案,因为它在挣扎数小时后拯救了我,并且可能对其他人有所帮助:

        正如大多数人所说 GC.Collect();不建议正常执行此操作,除非在极端情况下。作为这个运行垃圾收集的示例,正​​是我的方案的解决方案。

        我的程序在线程中对文件运行长时间运行的操作,然后从主线程中删除该文件。但是:当文件操作引发异常时,.NET 不会释放文件锁,直到垃圾被实际收集,即使长时间运行的任务被封装在 using 语句中。因此,程序必须在尝试删除文件之前强制进行垃圾回收。

        在代码中:

                var returnvalue = 0;
                using (var t = Task.Run(() => TheTask(args, returnvalue)))
                {
                    //TheTask() opens a file and then throws an exception. The exception itself is handled within the task so it does return a result (the errorcode)
                    returnvalue = t.Result;
                }
                //Even though at this point the Thread is closed the file is not released untill garbage is collected
                System.GC.Collect();
                DeleteLockedFile();
        

        【讨论】:

          【解决方案9】:

          这是一个替代建议。保持服务器 GC 的启用状态。然后根据用户定义的设置强制 GC 在应用内存超过您确定为关键级别的某个阈值时运行。

          请注意,如果您遵循这条路径,您实际上是在说明您更了解应该在何时运行垃圾收集,而 CLR 会这样做。大多数情况下,我发现 CLR 自己做的工作比我们干预它时做得更好。

          用于检查内存使用情况并跨所有代或指定代运行 GC 的代码

              long UsedMemory;
          //UsedMemory = GC.GetTotalMemory(false); // Not as reliable
          UsedMemory = System.Diagnostics.Process.GetCurrentProcess().PagedMemorySize64;
          if (UsedMemory > 1073741824) // One GB in bytes 1 X 1024 X 1024 X 1024
          {
              GC.Collect(); // Collect all generations
              //GC.Collect(2,GCCollectionMode.Forced);; Or collect a specific generation and force it to run now
          }
          

          【讨论】:

            猜你喜欢
            • 2015-02-12
            • 2011-04-01
            • 1970-01-01
            • 2019-10-01
            • 2019-06-07
            • 1970-01-01
            • 2010-09-16
            • 2012-12-06
            • 1970-01-01
            相关资源
            最近更新 更多