垃圾收集对象与长期运行的线程

时间:2017-08-09 11:56:34

标签: c# garbage-collection

如果有一个具有无限循环的对象,它是否会被垃圾收集(当线程正在运行时)?

我制作了一个程序来测试它,它似乎永远不会被垃圾收集,但我希望有更多经验的人来证实这一点。

编辑:我忘记添加示例了。这是我用过的例子。

class Program
{
    static void Main(string[] args)
    {
        WeakReference wr1 = InitializeClassWithLoop();
        WeakReference wr2 = InitializeClassWithoutLoop();

        GC.Collect(2);
        GC.Collect(2);
        GC.Collect(2);
        GC.WaitForPendingFinalizers();

        Thread.Sleep(30000);
        Console.WriteLine($"ClassWithLoop.IsAlive = {wr1.IsAlive}\nClassWithoutLoop.IsAlive = {wr2.IsAlive}\n");
        Console.ReadLine();
    }

    static WeakReference InitializeClassWithLoop()
    {
        var cs = new ClassWithLoop();
        return new WeakReference(cs);
    }

    static WeakReference InitializeClassWithoutLoop()
    {
        var cs = new ClassWithoutLoop();
        return new WeakReference(cs);
    }
}

public class ClassWithLoop
{
    public ClassWithLoop()
    {
        Thread thread = new Thread(Loop);
        thread.Start();
    }

    private void Loop()
    {
        int counter = 0;
        while (true)
        {
            counter++;
            Thread.Sleep(1000);
        }
    }
}

public class ClassWithoutLoop
{
    int counter;

    public ClassWithoutLoop()
    {
        counter = 5;
    }
}

结果是:
ClassWithLoop.IsAlive = True
ClassWithoutLoop.IsAlive = False

1 个答案:

答案 0 :(得分:1)

我只能假设你的意思是一个类里面有一个带有无限循环的方法:

public class A
{
  public void IDontEverEnd()
  {
    while(true) { }
  }
}

假设你做了这样的事情:

Task.Factory.StartNew(() => {
  new A().IDontEverEnd();
})

然后你的程序将保持活动状态,因为它只会在一个单独的线程上运行,但是 NO 它不会被垃圾回收;这是因为对IDontEverEnd的调用永远不会退出,因此对A实例的引用永远不会失效。

修改

正如mjwills在评论中提到的那样,即使正在对其执行某个方法, 有时也可能会对项目进行垃圾回收。

虽然在实践中,只要你不处理p / invoke东西,很可能这对你来说不重要。