GC.Collect()不立即收集?在一次聊天讨论中,我编写了这个控制台应用程序。代码:使用系统;类程序{staticvoidMain(string[]args){CreateClass();Console.Write("正在收集...");GC.收集();Console.WriteLine("完成");}staticvoidCreateClass(){SomeClassc=newSomeClass();}}classSomeClass{~SomeClass(){thrownewException();}}结果:正在收集...完成未处理的异常:System.Exception:引发了“System.Exception”类型的异常。在SomeClass.Finalize()中,我本以为应用程序会在打印Done之前崩溃。我不太在乎怎么做。我的问题是,为什么不呢?具有终结器的对象不能在单个垃圾收集过程中收集。这些对象被移动到f-reachable队列并保留在那里,直到调用终结器。只有在那之后,它们才能被垃圾收集。下面的代码更好,但你不应该依赖它:GC.Collect();GC.WaitForPendingFinalizers();GC.收集();此外,即使出于测试目的,在终结器中抛出异常在我看来也是残酷的。此外,终结器的一个有趣的副作用是:如果this引用存储在终结器中(通过将其分配给某个静态变量),具有终结器的对象仍然可以“复活”自身(有效地防止自身的垃圾收集)。你读过文档了吗?使用此方法尝试回收任何无法访问的内存。这不是命令,而是请求,它可能会或可能不会按您的意愿工作。无论如何这通常不是一个好主意(有时由于某些过程会产生很多非常小的短暂对象,在这种情况下调用GC.Collect可能是有益的,但这种情况很少见)。因为它看起来不像是在尝试解决一个真正的问题,而是用GC来解决它,所以这是我能提供的最好的建议。在最常见的垃圾收集器实现中,托管用户代码无法在垃圾收集周期内运行。Finalize方法算作用户代码。虽然理论上系统可以在Finalize方法执行时冻结所有其他用户代码,但这种行为增加了多核系统上垃圾回收的明显成本,也增加了死锁的可能性。为避免这些问题,系统不会将Finalize方法作为垃圾回收的一部分运行,而是构建一个需要运行Finalize方法的对象列表(此列表称为“一次性队列”)。列表本身被视为有根引用,因此可释放队列中的对象引用的任何对象都将被视为强根,至少在系统从队列中检索可释放对象、运行其Finalize方法并丢弃引用之前是这样。微软早期关于终结的文档非常混乱,因为它指出当这些方法运行时,可终结对象持有引用的对象可能不存在。事实上,所有这些对象都保证存在;不确定的是他们是否有Finalize方法。GC.Collect()将那些未引用的对象和终结器方法放入终结器队列中。它将通过调用finalize方法清除终结器队列。如果以上两点很清楚,那么您的代码在静态方法中持有对SomeClass的引用。这意味着它会持续到程序的主要方法执行为止。如果您希望应用程序在打印“完成”之前崩溃,那么首先使SomeClass对象无效,然后调用GC.Collect。它会将您的对象放在终结器队列中,但GC还想知道何时清除该队列。如果您希望GC清除该队列并调用终结器,请调用GC.WaitForPendingFinalizers()。你的线程会等到你的终结器被调用,然后它会继续。我修改了您想要的输出的代码。我没有抛出异常,而是在终结器中打印了一条语句。以上就是C#学习教程:GC。collect()不立即收集?如果分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注——classProgram{staticvoidMain(string[]args){CreateClass();Console.Write("正在收集...");GC.收集();GC.WaitForPendingFinalizers();Console.WriteLine("完成");控制台.ReadLine();}staticvoidCreateClass(){SomeClassc=newSomeClass();c=空;}}classSomeClass{~SomeClass(){Console.WriteLine("Finalized...");}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
