如何删除匿名对象并检查它们是否仍然存在于c#中

时间:2015-02-08 12:06:31

标签: c# garbage-collection

假设我有一个创建匿名对象的for循环:

using System;
using System.Threading;

namespace gctest
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Console.WriteLine ("Hello World!");
            for (int i = 0; i < 50; i++){
                myObject newobject = new myObject(i);
            }
        }
    }
    class myObject{
        int i;
        public myObject(int i){
            this.i = i;
            Announcer newannouncer = new Announcer (i); 
            Thread newthread = new Thread (newannouncer.Start);
            newthread.Start ();
        }
        ~myObject()  // destructor
        {
            Console.WriteLine ("=============================Object " + i + " HAS BEEN DESTROYED!=========================");
        }
    }
    class Announcer{
        int i;
        public Announcer(int i){
            this.i = i;
        }
        public void Start ()
        {
            while (true) {
                Console.WriteLine ("OBJECT" + i + " STILL EXISTS!");
                Thread.Sleep (500);
            }
        }
    }
}

运行for循环后,没有任何名称可以用来引用myObject实例,这意味着它们是未引用的,因此应该进行垃圾回收,对吧?但事实并非如此。他们继续打印消息,这意味着它们仍然存在,但我无法访问或删除它们。我也没有看到从析构函数方法打印的消息,这意味着它们没有被垃圾收集。

如何删除我创建的这些匿名对象并检查它们是否已不存在?我不仅希望线程停止,因为我可以在重新启动线程的myObjects中添加另一个方法。我希望完全删除myObject实例。

编辑:运行12分钟后,对象终于被垃圾收集了。迈克是对的。

2 个答案:

答案 0 :(得分:1)

公共语言运行时(CLR)跟踪线程,垃圾收集器不会删除它们。您需要停止线程并取消对线程对象的任何引用,并等待垃圾收集器为您执行脏工作。

答案 1 :(得分:1)

您的匿名对象确实会收集垃圾。你无法知道它们不是垃圾收集的;您看到的消息来自您启动的线程,而不是来自您的匿名对象。

如果您想查看是否收集了垃圾,可以执行以下两项操作之一:

  1. 最简单的方法是添加析构函数(~myObject())并打印“我正在垃圾收集!”来自它。

  2. 要做的最好的事情(虽然这项工作要多得多)是保持List WeakReference个{{1}}个对象,并定期浏览列表并查看是否任何目标引用都变为空。