这个问题仅供研究之用。
我读过很多关于C#的书,我总会想到这个问题。据我所知,C#是托管代码,当CLR决定何时运行垃圾收集时,会发生所有垃圾收集。让我们开始吧。
让我们假设我有一个简单的课程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!";
}
}
请批准或拒绝我的假设:
GC.Collect()
只是一个请求来进行垃圾收集,它不会立即在第2行运行。此行可能以x毫秒/秒执行。
在我看来,方法System.GC.Collect();
只是告诉垃圾收集器垃圾收集器应该运行垃圾收集,但真正的垃圾收集可能会以x毫秒/秒发生
只有垃圾收集器知道何时运行垃圾收集。如果第0代中有可用空间,则第2行中不会进行垃圾收集: row2: System.GC.Collect();
由于我们在托管环境中编程,因此无法立即运行垃圾收集,只有CLR决定何时运行垃圾收集。垃圾收集可以x毫秒/秒运行或者垃圾收集可能无法运行因为在调用方法GC.Collect()
之后,第0代中有足够的空间来创建新对象。程序员可以做的只是让CLR按方法GC.Collect()
运行垃圾收集。
更新
我看过this msdn article about GC.Collect Method ()
.。但是,当我开始真正清除未引用的对象时,我不清楚。 MSDN说:
GC.Collect Method()强制立即对所有垃圾进行收集 代。
但是,在备注中,我读过这篇文章:
使用此方法尝试回收所有无法访问的内存。它 执行所有代的阻塞垃圾收集。
答案 0 :(得分:5)
简短回答
调用GC.Collect()
将执行完整的垃圾收集并等待它完成,但它不会等待任何挂起的终结器运行。
LONG ANSWER
您在假设中部分正确,因为运行终结器的GC在一个或多个后台线程中运行。 (但请参阅本答复末尾的脚注。)
但是, 可以在您致电GC.Collect()
后致电GC.WaitForFullGCComplete()
和GC.WaitForPendingFinalizers()
等待完整的GC完成:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.WaitForFullGCComplete();
但是,请注意未指定运行终结器的线程,因此无法保证此方法将终止。
请注意,您通常不应以这种方式使用GC;我假设您有一个特殊情况需要解决,或者您是出于研究目的而这样做。
我见过的唯一有效案例是应用程序正在关闭,并且您希望(尝试)确保所有终结器都已运行 - 例如,因为它们将刷新日志文件等。
如上所述,这仍然不能保证所有终结器都已运行;它是你能做的最好的事情。
回答你的观点(5):
GC.Collect()的文档说明:
强制所有世代立即进行垃圾收集。
因此将强制使用GC。
文档还说明:
使用此方法尝试回收所有无法访问的内存。
使用"试试"这仅仅意味着即使运行完整的GC,也不一定会回收所有无法访问的内存。有几个原因可能发生,例如,终结器可能会阻止。
<强>脚注强>
.Net 4.5 allows you to specify whether GC.Collect()
is blocking or not。
事实上,GC.Collect()
的文档指出它执行所有代的阻塞垃圾收集,这似乎与我上面的陈述相矛盾。但是,对于是否真的存在这种情况似乎存在一些混淆。
请参阅示例this thread。
答案是这样的: 因此,如果您不需要等待终结者,您只需要致电GC.Collect()
默认等待所有代的GCed,但它不会等待挂起的终结器,它总是在一个单独的线程中执行。 / p>
GC.Collect()
,而无需等待其他任何事情。
答案 1 :(得分:1)
有两个GC,从您的代码中,我相信您想了解Workstation GC。通过在完整集合期间同时运行来最小化暂停? Workstation GC使用第二个处理器同时运行集合,最大限度地减少延迟,同时降低吞吐量。如果服务器GC没有正常工作,我们应该只担心GC行为。如果您根据工作站GC在代码中添加GC.collect(),那么在服务器GC上可能没用。
服务器GC旨在实现最大吞吐量,并以非常高的性能进行扩展。服务器上的内存碎片比工作站上的问题严重得多,使垃圾收集成为一个有吸引力的主张。在单处理器场景中,两个收集器的工作方式相同:工作站模式,没有并发收集
我很困惑这个使用这个方法来尝试,我认为垃圾收集可能不会发生,因为CLR决定有足够的空间来创建新对象。我是对的吗?
对于workstaion GC,GC.Collect将尽快开始收集,您可以安全地假设它立即收集。