GC.Collect()之后是否立即运行垃圾回收? [英] Does garbage collection run immediately after GC.Collect()?

查看:179
本文介绍了GC.Collect()之后是否立即运行垃圾回收?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题仅是出于研究目的.

我已经阅读了很多有关C#的书,这个问题总是浮现在我脑海.据我了解,C#是托管代码,并且所有垃圾收集都是在CLR决定何时运行垃圾收集时发生的.我们开始吧.

让我们想象一下,我有一个简单的类 Student :

 公共班级学生{public int IdStudent {get;放;}公共字符串名称{get;放;}公共字符串姓氏{get;放;}}班级计划{静态void Main(string [] args){这是第1行:Person person = new Person(){IdPerson = 1,Name ="Bill",SurName ="Collins"};这是第2行:System.GC.Collect();这是row3:string str ="Hello World!";}} 

请批准或拒绝我的假设:

  1. 我是否可以在 row2 上不立即运行垃圾回收?
  2. GC.Collect()只是一个请求,用于进行垃圾收集,该垃圾收集不会在第2行立即运行.此行可能以x毫秒/秒的速度执行.在我看来,方法 System.GC.Collect(); 只是对垃圾收集器说,垃圾收集器应该运行垃圾收集,但是真正的垃圾收集可能会在x毫秒/秒内发生>

  3. 只有垃圾收集器知道何时将运行垃圾收集.而且,如果第0代中有可用空间,则 row2: row2:System.GC.Collect();

    li>
  4. 由于我们正在托管环境中进行编程,因此无法立即运行垃圾收集,只有CLR决定何时运行垃圾收集.垃圾收集可以x毫秒/秒或垃圾回收可能无法运行,因为调用方法 GC.Collect()后,第0代中有足够的空间来创建新对象.程序员可以做的就是通过方法 GC.Collect()来要求CLR运行垃圾回收.

更新:

我已阅读这篇有关 GC.Collect方法().的msdn文章.但是,我不清楚何时开始真正清除未引用的objets.MSDN说:

GC.Collect方法()强制立即对所有垃圾回收几代人.

但是,在备注中,我已经阅读过此内容:

使用此方法尝试回收所有不可访问的内存.它执行所有世代的阻塞垃圾收集.

  1. 我对这个使用此方法进行尝试" 感到困惑,并且我认为可能不会发生垃圾回收 ,因为 CLR 决定在那里有足够的空间来创建新对象.我说的对吗?

解决方案

缩短答案

调用 GC.Collect()将执行完整的垃圾回收并等待其完成,但是不会等待任何未完成的终结器运行.

长答案

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

但是,可以通过调用 GC.WaitForPendingFinalizers() .Collect():

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

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

请注意,通常不应以这种方式使用GC.我认为您有一个特殊情况需要解决,或者您出于研究目的而这样做.

我看到的唯一有效的情况是关闭应用程序时,并且您想要(尝试)确保所有终结器都已运行-例如,因为它们将刷新日志文件等.

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

针对您的观点(5):

GC.Collect()的文档指出:

强制立即进行所有世代的垃圾回收.

因此,此强制执行GC.

文档还指出:

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

在此使用"try"一词仅意味着即使运行了完整的GC,也不一定会收回所有无法访问的内存.可能有多种原因发生,例如,终结器可能会阻塞.

脚注

.Net 4.5 可让您指定 GC.Collect()是否被阻止.

实际上, GC.Collect()的文档指出它执行了所有世代的阻塞垃圾收集,这似乎与我上面的陈述相矛盾.但是,对于是否确实如此,似乎有些困惑.

例如参见此线程.

答案是这样的: GC.Collect()默认情况下将 等待所有世代的GC,但它不会等待待决的终结器(通常是终结器)在单独的线程中执行.

因此,如果您不需要等待终结器,则只需调用 GC.Collect()即可,而无需等待其他任何东西.

The question is just for research purposes.

I've read many books about C# and this question always comes to my mind. What I understood that C# is managed code and all garbage collection occurs when CLR decides when to run garbage collection. Let's start.

Let's imagine that I have simple class Student:

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!";
    }        
}

Please, approve or reject my suppositions:

  1. Am I right that garbage collection is not run immediately at row2?
  2. GC.Collect() is just a request to make a garbage collection which DOES NOT RUN IMMEDIATELY at row2. This row maybe executed in x milliseconds/seconds. In my view, method System.GC.Collect(); just says to garbage collector that garbage collector should run garbage collection, but real garbage collection may occur in x milliseconds/seconds

  3. Only garbage collector knows when garbage collection will be run. And If there is free space in Generation 0, then garbage collection will not occur in the row2: row2: System.GC.Collect();

  4. It is not possible to run garbage collection immediately as we are programming in managed environment and only CLR decides when to run garbage collection. Garbage collection can be run in x milliseconds/seconds or garbage collection maybe not run cause there is enough space in generation 0 to create new objects after calling method GC.Collect(). What programmer can do is just ask CLR to run garbage collection by method GC.Collect().

Update:

I've read this msdn article about GC.Collect Method ().. However, it is unclear to me when real clearing of unreferenced objets is started. MSDN says:

GC.Collect Method () forces an immediate garbage collection of all generations.

However, in Remarks I've read this one:

Use this method to try to reclaim all memory that is inaccessible. It performs a blocking garbage collection of all generations.

  1. I am confused by this "Use this method to TRY" and I think that garbage collection may not occur cause CLR decides that there is enough space to create new objects. Am I right?

解决方案

SHORT ANSWER

Calling GC.Collect() will do a complete garbage collection and wait for it to finish, but it will NOT wait for any pending finalizers to run.

LONG ANSWER

You're partially right in your suppositions because the GC for running finalizers runs in one or more background threads. (But see the footnote at the end of this answer.)

However, it is possible to wait for a complete GC to finish by calling GC.WaitForFullGCComplete() and GC.WaitForPendingFinalizers() after you have called GC.Collect():

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

However, be aware that The thread on which finalizers are run is unspecified, so there is no guarantee that this method will terminate.

Note that you should not normally use the GC in this way; I assume you have a special case that you need to address, or you are doing this for research purposes.

The only valid case I've seen for this is when an application is closing, and you want to (try to) ensure that all finalizers have been run - because, for example, they will flush log files etc.

As noted above, this still doesn't guarantee that all finalizers have been run; it's just the best you can do.

In answer to your point (5):

The documentation for GC.Collect() states:

Forces an immediate garbage collection of all generations.

So this will force a GC.

The documentation also states:

Use this method to try to reclaim all memory that is inaccessible.

The use of the word "try" there merely means that even if a full GC is run, not all inaccessible memory will necessarily be reclaimed. There are several reasons that can occur, for example, a finalizer may block.

Footnote

.Net 4.5 allows you to specify whether GC.Collect() is blocking or not.

In fact, the documentation for GC.Collect() states that It performs a blocking garbage collection of all generations, which would appear to contradict my statements above. However, there seems to be some confusion as to whether this really is the case.

See for example this thread.

The answer is this: GC.Collect() will by default wait for all generations to be GCed, but it will NOT wait for pending finalizers, which are always executed in a separate thread.

Hence if you do not need to wait for finalizers, you ONLY need to call GC.Collect() and you do NOT need to wait for anything else.

这篇关于GC.Collect()之后是否立即运行垃圾回收?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆