大家好,
如果我在一个长时间运行的方法中(不一定是CPU密集型...只是长时间运行)将一个大对象设置为null,它是否立即可以进行垃圾回收,或者需要等到该方法完成后该对象才准备好进行垃圾回收?
大家好,
如果我在一个长时间运行的方法中(不一定是CPU密集型...只是长时间运行)将一个大对象设置为null,它是否立即可以进行垃圾回收,或者需要等到该方法完成后该对象才准备好进行垃圾回收?
这种方法不需要完全执行,但如果GC可以确定您不会再次从中读取变量,则无需将变量设置为null。例如:
public void Foo()
{
SomeObject x = new SomeObject();
// Code which uses x
Console.WriteLine("Eligible for collection");
// Code which doesn't use x.
}
在指定点,该对象有资格进行收集 - 当然,假设没有其他东西保留了对它的引用。重要的是是否会有任何东西能够再次读取该值。您甚至可以将变量分配为不同的值,然后读取它,只要垃圾回收器知道它不会再次看到原始值,那就不会作为GC根。例如:
using System;
class Bomb
{
readonly string name;
public Bomb(string name)
{
this.name = name;
}
~Bomb()
{
Console.WriteLine(name + " - going boom!");
}
public override string ToString()
{
return name;
}
}
class Test
{
static void Main()
{
Bomb b = new Bomb("First bomb");
Console.WriteLine("Using bomb...");
Console.WriteLine(b);
Console.WriteLine("Not using it any more");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Creating second bomb...");
b = new Bomb("Second bomb");
Console.WriteLine("Using second bomb...");
Console.WriteLine(b);
Console.WriteLine("End of main");
}
}
输出:
Using bomb...
First bomb
Not using it any more
First bomb - going boom!
Creating second bomb...
Using second bomb...
Second bomb
End of main
Second bomb - going boom!
using System;
class Bomb
{
int x = 10;
~Bomb()
{
Console.WriteLine("Boom!");
}
public void GoBang()
{
Console.WriteLine("Start of GoBang");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("x={0}", x);
Console.WriteLine("No more reads of x");
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Returning");
}
}
class Test
{
static void Main()
{
Bomb b = new Bomb();
b.GoBang();
Console.WriteLine("Still in Main");
}
}
输出:
Start of GoBang
x=10
No more reads of x
Boom!
Returning
Still in Main
(请不要在调试器中运行此代码,因为调试器会延迟垃圾回收以便您可以查看变量。)
需要注意的一点是:您的问题谈到了将一个“对象”设置为null……这个概念不存在。您只能将一个“变量”设置为null。值得区分这两者之间的差别。
null
之前。假设之前的值不再被任何东西引用,它将立即符合垃圾回收的条件。