C# 垃圾收集是否在GC.Collect()之后立即运行?

C# 垃圾收集是否在GC.Collect()之后立即运行?,c#,.net,garbage-collection,garbage,C#,.net,Garbage Collection,Garbage,这个问题只是为了研究目的 我读过很多关于C#的书,我总是想到这个问题。据我所知,C#是托管代码,所有垃圾收集都发生在CLR决定何时运行垃圾收集时。让我们开始吧 让我们假设我有一个简单的类学生: public class Student { public int IdStudent { get; set; } public string Name { get; set; } public string Surname { get; set; } } class Progra

这个问题只是为了研究目的

我读过很多关于C#的书,我总是想到这个问题。据我所知,C#是托管代码,所有垃圾收集都发生在CLR决定何时运行垃圾收集时。让我们开始吧

让我们假设我有一个简单的类
学生

public class Student
{
    public int IdStudent { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
}
class Program
{
      static void Main(string[] args)
      {
This is row1:    Person person = new Person() {IdPerson=1, Name="Bill", SurName="Collins"};
This is row2:    System.GC.Collect();
This is row3:    string str="Hello World!";
    }        
}
请批准或拒绝我的假设:

  • 第2行中没有立即运行垃圾收集,这对吗
  • GC.Collect()
    只是一个请求,用于进行垃圾收集,该垃圾收集不会立即在第2行运行。此行可能在x毫秒/秒内执行。 在我看来,方法
    System.GC.Collect()只是告诉垃圾收集器垃圾收集器应该运行垃圾收集,但是真正的垃圾收集可能会在x毫秒/秒内发生

  • 只有垃圾收集器知道何时运行垃圾收集。如果第0代中有可用空间,则不会在行2:
    行2:System.GC.Collect()中进行垃圾回收

  • 不可能立即运行垃圾收集,因为我们正在托管环境中编程,只有CLR决定何时运行垃圾收集。垃圾收集可以在x毫秒/秒内运行,或者垃圾收集可能不运行因为第0代中有足够的空间创建新的垃圾收集调用方法
    GC.Collect()
    后的对象。程序员可以做的只是让CLR通过方法
    GC.Collect()
    运行垃圾收集

  • 更新:

    我读过。然而,我不清楚何时开始真正清除未引用的对象。MSDN说:

    Collect方法()强制立即对所有 几代人

    然而,在评论中,我读到了这一条:

    使用此方法尝试回收所有不可访问的内存。信息技术 执行所有代的阻塞垃圾收集

  • 我对这个“使用此方法尝试”感到困惑,我认为垃圾收集可能不会发生因为CLR决定有足够的空间来创建新对象。我说得对吗

  • 简短回答

    调用
    GC.Collect()
    将执行完整的垃圾收集并等待它完成,但不会等待任何挂起的终结器运行

    长答案

    您的假设部分正确,因为运行终结器的GC在一个或多个后台线程中运行。(但请参见本答案末尾的脚注。)

    但是,可以通过调用和调用
    GC.Collect()
    ,等待完成GC:

    但是,请注意,运行终结器的线程是未指定的,因此不能保证此方法将终止

    注意,您通常不应该以这种方式使用GC;我假设你有一个特殊的情况,你需要解决,或者你这样做是为了研究目的

    我见过的唯一有效的情况是当应用程序关闭时,您希望(尝试)确保所有终结器都已运行,因为,例如,它们将刷新日志文件等

    如上所述,这仍然不能保证所有终结器都已运行;这是你能做的最好的了

    关于你的第(5)点:

    GC.Collect()的文档说明:

    强制立即对所有代进行垃圾收集

    所以这将强制GC

    文件还指出:

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

    在那里使用“try”一词仅仅意味着即使运行完整的GC,也不一定会回收所有不可访问的内存。可能会出现以下几种原因,例如,终结器可能会阻塞

    脚注

    .Net 4.5

    事实上,
    GC.Collect()
    的文档说明它执行所有代的阻塞垃圾收集,这似乎与我上面的陈述相矛盾。然而,对于是否真的是这样,似乎存在一些困惑

    例如,见

    答案是:
    GC.Collect()
    默认情况下将等待所有代被GCed,但它不会等待挂起的终结器,这些终结器总是在单独的线程中执行


    因此,如果您不需要等待终结器,您只需要调用
    GC.Collect()
    ,而不需要等待任何其他操作。

    有两个GC,我相信您希望从您的代码中了解工作站GC。哪种方法通过在完整收集期间并发运行来最小化暂停?工作站GC使用第二个处理器并发运行收集,在减少吞吐量的同时最小化延迟。如果服务器GC没有正常工作,我们应该只担心GC的行为。如果您按照工作站GC在代码中添加GC.collect(),则这在服务器GC上可能是无用的

    服务器GC是为实现最大吞吐量而设计的,并且具有非常高的性能。服务器上的内存碎片是一个比工作站上严重得多的问题,这使得垃圾收集成为一个有吸引力的提议。在单处理器场景中,两个采集器的工作方式相同:工作站模式,没有并发采集

    我对使用这种方法进行尝试感到困惑,我认为垃圾收集可能不会发生,因为CLR决定有足够的空间来创建新对象。我说得对吗


    对于workstaion GC,GC.Collect将尽快开始收集,您可以假设它会立即安全收集。

    哦,它肯定会运行,但您是否询问它是否收集特定的内容
    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.WaitForFullGCComplete();