怎样才能知道一个对象是否已经被GC回收?或怎样知道一个对象正在被GC回收?这时能否触发一个事件

解决方案 »

  1.   

    http://www.xmlasp.net/n1328c12.aspx这个或许对lz有点帮助
      

  2.   

    在对象不使用的时候.net会根据一个算法来回收资源.如果楼主不放心也可继承idispose接口来手动销毁对象.
      

  3.   

    楼主给的分真多啊,口水ing!
    给你个示例,你就后悔了:我怎么给这么多分啊???using System;
    using System.Windows.Forms;
    namespace GCTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                B b = new B();
            }
        }
        public class B
        {
            ~B()//析构函数,垃圾回收时调用,这意味着对继承链中的所有实例递归地调用 Finalize 方法
            {
                MessageBox.Show("我销毁了啊,你别拦住我");
            }
        }
    }对话框会在一段时间后也消失,因为它是B的资源,也被回收了
      

  4.   

    给回收添加通知:using System;
    using System.Windows.Forms;
    namespace GCTest
    {
        public delegate void GCEventHandler();
        class Program
        {
            static void Main(string[] args)
            {
                B b = new B();
                b.disposeHandler += new GCEventHandler(b_disposeHandler);
            }        static void b_disposeHandler()
            {
                MessageBox.Show("正在回收B");
            }
        }
        public class B
        {
            public event GCEventHandler disposeHandler;
            public B()
            {
                disposeHandler += new GCEventHandler(OnGC);
            }
            ~B()//析构函数,垃圾回收时调用
            {
                disposeHandler();
            }
            void OnGC()
            {
                Console.WriteLine("GCEventHandler was called");
            }
        }
      

  5.   

    gc方法会调用析构函数,但是并没有立刻释放内存,就象楼上的弟兄的例子一样,MessageBox.Show的内容还是可以被显示出的,通常说有gc后要两个周期后才可以被系统回收内存,第一个周期运行finalizer,第二个周期回收内存.要熟悉gc方法的原理还是从.net的stack与heap开始吧,推荐楼主一篇文章,希望这是楼主想要的
    http://blog.csdn.net/zjunqiang/archive/2007/10/20/1834129.aspx
      

  6.   

    自己写一个吧。
    楼主我就缺分,能碰见你太好了,感觉找到党了!
    using System;namespace GC_Event
    {
        // 定义事件委托
        public delegate void ActionEventHandler(object sender, MyEventArgs e);    // 定义事件参数
        public class MyEventArgs : EventArgs
        {
            // 根据你的实际需要添加变量
            public int Count = 0;        // 这个一定要保留,它是开关,控制 GC 是否引发用户事件
            public bool Stop = true;
        }    // 给类起名叫"烈士",我真是太有才了!
        public class Martyr
        {
            // 静态事件参数变量,通过它存储你要传达给事件的信息
            public static MyEventArgs e = new MyEventArgs();        // 生成事件变量,也是静态的,存储你让事件引发的方法集合
            public static event ActionEventHandler Action = null;        // 启动对 GC 的跟踪
            public static void Start()
            {
                // 有 e 被用户定义为 null 的可能性,代码写强壮点吧
                if (Martyr.e != null && Martyr.e.Stop == true)
                {
                    // 把控制无限循环开关打开,不间断的跟踪 GC
                    Martyr.e.Stop = false;
                    // 生成一个动态对象,然后直接抛弃,等着GC来回收
                    // 从这点上来说,这个动态对象绝对是烈士
                    new Martyr();
                }
            }        // 停止对 GC 的跟踪
            public static void Stop()
            {
                // 把开关关闭,下次垃圾回收就不会触发事件,并停止循环,这个烈士真正的安息了
                if (Martyr.e != null)
                    Martyr.e.Stop = true;
            }        // 析构器,本方法的核心
            // GC只要一工作,就一定会来执行不存在引用的对象的析构器,算是遗体告别仪式吧
            // 我不是不尊敬烈士昂,只不过这个词比较容易让人理解
            ~Martyr()
            {
                // 如果开关不存在了,或者开关关闭,就老老实实地回收,结束
                if (Martyr.e != null)
                    if (!Martyr.e.Stop)
                    {
                        // 如果开关开着,就触发事件,同样代码写强壮一点,不执行空事件
                        if (Martyr.Action != null)
                            OnAction();
                        // 革命尚未成功,同志仍须努力
                        // 倒下我一个,还有后来人
                        // 再制造个烈士躺那,跟踪下一次 GC 的动作
                        new Martyr();
                    }
            }        // 触发事件
            private void OnAction()
            {
                // 告诉方法是烈士在调用它,虽然躺那了,精神还在,this关键字仍然指向本体
                // 参数 e 用那个静态的, e 也算是包罗万象了
                Martyr.Action(this, Martyr.e);
            }
        }
        class Program
        {
            static void Main(string[] args)
            {
                // 把自己的方法传给烈士要执行的事件
                Martyr.Action += new ActionEventHandler(Program.Process);            // 启动对 GC 的跟踪
                Martyr.Start();
                // 人为制造垃圾回收
                for (int i = 0; i < 100; i++)
                {
                    Martyr.e.Count++;
                    int[] j = new int[1000000];
                    GC.Collect();
                    //Array.Clear(j, 0, 1000000);
                }
                Console.WriteLine("第1次试验结束了");
                Console.ReadKey();
                // 停止对 GC 的跟踪,立杆见影,即使马上 GC 动作,也不会触发事件了
                Martyr.Stop();
                // 试验一下!
                for (int i = 100; i < 200; i++)
                {
                    Martyr.e.Count++;
                    int[] j = new int[1000000];
                    GC.Collect();
                    //Array.Clear(j, 0, 1000000);
                }
                Console.WriteLine("第2次试验结束了");
                Console.ReadKey();
                // 再做个试验,自然的执行垃圾回收看看
                Martyr.e.Count = 999;
                Martyr.Start();
                // 这个方法不一定会产生 GC 的动作,看内存里垃圾数量怎么样了
                GC.Collect();            // 用完别忘了跟烈士告别,否则,嘿嘿,自己试试吧!
                // 貌似诈尸
                Martyr.Stop();
                Console.WriteLine("第3次试验结束了");
                Console.ReadKey();
            }        // 用户方法
            static void Process(object sender, MyEventArgs e)
            {
                // 判断是不是烈士触发的
                if (sender is Martyr)
                    Console.WriteLine("循环到第 {0} 次后,垃圾回收器工作,触发事件", e.Count);
            }
        }
    }
      

  7.   

    一般来说需要知道这个信息的是控件类,而控件类一般都有IsDisposed属性:Control.IsDisposed 属性 
    例如:
    if (this.IsDisposed)
    {
        //已释放了
    }如果没有这样的属性,一般在实现IDisposable 接口的时候会加入这么一个属性来表示对象是否被调用过了Dispose方法而不能再被使用了。
      

  8.   

    不错
    析构听CLR的
    12楼的例子很好,构造函数再加上 public Martyr() { Console.WriteLine("我来了!"); }
    就更好了!
      

  9.   

    在你的这个对象里调用一个方法,来判断这个OBJ 是否为空啊?
      

  10.   

     ~Martyr()
            {
              
                // 如果开关不存在了,或者开关关闭,就老老实实地回收,结束
                if (Martyr.e != null)
                {
                    Console.WriteLine("我可能得走了!");
                    if (!Martyr.e.Stop)
                    {
                        // 如果开关开着,就触发事件,同样代码写强壮一点,不执行空事件
                        if (Martyr.Action != null)
                            OnAction();
                        // 革命尚未成功,同志仍须努力
                        // 倒下我一个,还有后来人
                        // 再制造个烈士躺那,跟踪下一次 GC 的动作
                        new Martyr();
                    }
                    else { Console.WriteLine("我被踢走了!"); }
                }
               
            }
      

  11.   

    怎样才能知道一个对象是否已经被GC回收?
    ------------
    object o = new object();
    WeakReference wref = new WeakReference(o);
    //...
    if (!wref.IsAlive)
       Console.WriteLine("已经被GC回收了。");
    如果对象能复活的话,用下面这个:
    WeakReference wref = new WeakReference(o, true);
      

  12.   

      谢谢22楼支持,不过有个误解,我说明一下。  实际上 GC 调用了 ~Martyr() 析构器后,仅执行一些处理,例如,释放 martyr 对象调用的非托管资源,这里我改成了触发规定事件,并生成新的 martyr 对象进行下一次跟踪。  下一次 GC 工作的时候,才能真正释放已经执行过了 ~Martyr() 析构器的 martyr 对象占用的内存,所以我 12 楼那个程序真正的目的是跟踪 CLR 的 GC 动作。 martyr 对象并不是要观察的对象。  不过在 GC 动作后引起的规定事件里,可以检查自己关心的对象是否已经真正被释放掉。例如让那些对象的析构器更改某个静态变量,每次在 GC 动作后引起的规定事件里读取这个变量,如果值发生了变化,那么自己真正关心的对象的析构器已经工作过了,下一次 GC 工作时会真正释放掉它。
      

  13.   

    Microsoft Content Management Server 2002 .NET Class Reference  
    Resource Members  
    See Also   Methods  Properties   
     Collapse All Expand All  Members Options: Show All Members Options: Filtered  
     Include Inherited Members 
     Include Protected Members 
     .NET Compact Framework Members Only 
    Represents an item, such as an image or other multimedia file, stored in a Microsoft Content Management Server (MCMS) 2002 ResourceGallery.The following tables list the members exposed by the Resource type.  Public Properties 
      Name  Description  
      CanDelete   Gets a value indicating whether the current User has sufficient rights to delete this class instance.(inherited from HierarchyItem) 
      CanSetContent  Gets a value indicating whether the current user has sufficient rights to change the content of this Resource using SetContentFromFile. 
      CanSetProperties   Gets a value indicating whether the current User has sufficient rights to modify the properties of this class instance.(inherited from HierarchyItem) 
      CanUseForAuthoring  Gets a value indicating whether the current user has sufficient rights to use this Resource for authoring a Posting. 
      CreatedBy   Gets the User that created this class instance.(inherited from HierarchyItem) 
      CreatedDate   Gets the coordinated universal time (UTC) when the HierarchyItem was created.(inherited from HierarchyItem) 
      Description   Gets or sets descriptive text for this class instance.(inherited from HierarchyItem) 
      DisplayName  Gets or sets the name displayed for a Resource in the MCMS 2002 Web site. 
      DisplayPath  Gets the fully-qualified display path of a Resource. 
      FileExtension  Gets the extension of the file from which the Resource content was set. 
      Guid   Gets a string representation of the globally unique identifier (GUID) for this object.(inherited from HierarchyItem) 
      IsDeleted   Gets a value indicating whether this class instance has been deleted, regardless of whether the deletion has been committed. (inherited from HierarchyItem) 
      

  14.   

    详细信息看MSDN:Resource class [MCMS]
      

  15.   

    但是有个问题:
    如果你的对象中的某个字段被其他对象引用,那么垃圾回收器是不会回收这个对象的...........
    就像第一个例子中的那个.如果将 B b = new B();这个语句放到一个winform程序里,那么在弹出对话框之后对话框是不会消失的............
      

  16.   

    给你要管理的每个对象分配一个ID,在对象析构的时候,把其ID写入到一个全局Hashtable里,后面你以ID为Key就可以判断是否析构了:~XXX
    {
        _gcObj[ID] = 1;//这里可以任意写,但不要写成 _gcObj[ID] = this,否则不能释放
    }程序判断:
        if (_gcObj[ID] != null)
        {
            // 对象已回收   
        }
      

  17.   

    楼上不对,析构器被执行后,对象并未被回收,只是完成了析构器里的任务,下一次垃圾回收时才真正被回收掉,不信可以看msdn对析构器的解释,我 27 楼已经详细说明了怎么跟踪 GC ,那才是正路子,准备被回收,正在被回收和已经被回收都能清楚地知道
      

  18.   

    本来就是MICROSOFT提供的类大家搞定这么复杂,累不累啊??????
      

  19.   

    第一个问题应该用个弱引用行吧.
    第二个问题也许能通过获取net框架里面的销毁对象列表可以实现.
      

  20.   

    我记得thinking in Java 上有讲关于垃圾回收的,原理应该和。net一样,所以看看吧
      

  21.   

    是这样的:如果对象已经被GC回收,那么很明显你是无法访问它的.而如果你可以访问到它,就说明这个对象还没被GC回收.
      

  22.   

    12楼貌似不对吧。他也可能是紧紧回收你的烈士啊。
    你添加个例子:
    {System.Threading.Timer t = new System.Threading.Timer(Collect, null, 0, 200);
               Console.ReadKey();
                t.Dispose();
    }
    private static void Collect(object o)
            {
                Console.WriteLine("Timer执行");
                GC.Collect();
            }
    按理说,这里t是不会被回收的,因为后面还有引用。但是执行效果是,gc一直在回收