读书人

怎样才能知道一个对象是否已经被GC回收

发布时间: 2012-05-31 12:19:24 作者: rapoo

怎样才能知道一个对象是否已经被GC回收?

怎样才能知道一个对象是否已经被GC回收?

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

[解决办法]
楼主给的分真多啊,口水ing!
给你个示例,你就后悔了:我怎么给这么多分啊???

C# code
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("我销毁了啊,你别拦住我");        }    }}
[解决办法]
给回收添加通知:
C# code
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");        }    }
[解决办法]
自己写一个吧。
楼主我就缺分,能碰见你太好了,感觉找到党了!
C# code
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);        }    }} 


[解决办法]

C# code
 ~Martyr()        {                      // 如果开关不存在了,或者开关关闭,就老老实实地回收,结束            if (Martyr.e != null)            {                Console.WriteLine("我可能得走了!");                if (!Martyr.e.Stop)                {                    // 如果开关开着,就触发事件,同样代码写强壮一点,不执行空事件                    if (Martyr.Action != null)                        OnAction();                    // 革命尚未成功,同志仍须努力                    // 倒下我一个,还有后来人                    // 再制造个烈士躺那,跟踪下一次 GC 的动作                    new Martyr();                }                else { Console.WriteLine("我被踢走了!"); }            }                   }
[解决办法]
怎样才能知道一个对象是否已经被GC回收?
------------
C# code
object o = new object();WeakReference wref = new WeakReference(o);//...if (!wref.IsAlive)   Console.WriteLine("已经被GC回收了。");
[解决办法]
  谢谢22楼支持,不过有个误解,我说明一下。

  实际上 GC 调用了 ~Martyr() 析构器后,仅执行一些处理,例如,释放 martyr 对象调用的非托管资源,这里我改成了触发规定事件,并生成新的 martyr 对象进行下一次跟踪。

  下一次 GC 工作的时候,才能真正释放已经执行过了 ~Martyr() 析构器的 martyr 对象占用的内存,所以我 12 楼那个程序真正的目的是跟踪 CLR 的 GC 动作。 martyr 对象并不是要观察的对象。

  不过在 GC 动作后引起的规定事件里,可以检查自己关心的对象是否已经真正被释放掉。例如让那些对象的析构器更改某个静态变量,每次在 GC 动作后引起的规定事件里读取这个变量,如果值发生了变化,那么自己真正关心的对象的析构器已经工作过了,下一次 GC 工作时会真正释放掉它。
[解决办法]
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)

[解决办法]
但是有个问题:
如果你的对象中的某个字段被其他对象引用,那么垃圾回收器是不会回收这个对象的...........


就像第一个例子中的那个.如果将 B b = new B();这个语句放到一个winform程序里,那么在弹出对话框之后对话框是不会消失的............
[解决办法]
给你要管理的每个对象分配一个ID,在对象析构的时候,把其ID写入到一个全局Hashtable里,后面你以ID为Key就可以判断是否析构了:

~XXX
{
_gcObj[ID] = 1;//这里可以任意写,但不要写成 _gcObj[ID] = this,否则不能释放
}

程序判断:
if (_gcObj[ID] != null)
{
// 对象已回收
}
[解决办法]
楼上不对,析构器被执行后,对象并未被回收,只是完成了析构器里的任务,下一次垃圾回收时才真正被回收掉,不信可以看msdn对析构器的解释,我 27 楼已经详细说明了怎么跟踪 GC ,那才是正路子,准备被回收,正在被回收和已经被回收都能清楚地知道
[解决办法]
第一个问题应该用个弱引用行吧.
第二个问题也许能通过获取net框架里面的销毁对象列表可以实现.
[解决办法]
Resource.*****.IsDeleted
[解决办法]
析构函数是在对象即将析构前被调用,调用之后就被回收了,在多线程的环境里也许会有些问题,如果对精确度要求很高,可以通过加锁的方式来串行化。相比27楼,我这个方法简单。不过27楼确实费了不少气力,楼主应该把分都给他。呵呵
[解决办法]
执行的析构函数.
并不代表 GC已经回收对象.

读书人网 >C#

热点推荐