GC的初步接触——不能够使用已释放的对象

        最近在进行项目开发的时候,有个地方需要弹出等待提示框,然后因为涉及只能让其是一个对象的,所以使用到了单例模式,在我的博客里面有详细介绍:https://blog.csdn.net/qq_41061437/article/details/99838057。在之后另外一个弹框提示中,我发现了一些问题,然后这个问题牵扯出了C#中的GC,深入的自己还在研究中,这里先讲述一些初步接触。

        因为需要弹框提示,我用了一个窗体来进行,然后这个框只能是一个对象,否则再次触发,又会弹出同样的新的窗口,因此我这里采用了饿汉式的单例:

public partial class WaitLoading : Form
{
    private static WaitLoading waitLoading = new WaitLoading();
 
    private WaitLoading()
    {
        InitializeComponent();
    }
 
    public static WaitLoading GetInstance()
    {
        return waitLoading;
    }

}

        在使用过程中,当不需要这个框的时候,我应该调用这个对象的Close方法来关闭它,直到这里都没有问题,但是如果需要再次调用这个窗口,使用Show方法的时候就会出错。程序会提示“不能够引用已释放的对象”。我突然想到,我调用Close方法,应该是将这个对象释放了,然后我用的单例模式,导致这里创建不了对象了,于是我换了个懒汉式的单例:

public partial class WaitLoading : Form
{
    private static WaitLoading waitLoading;
 
    private WaitLoading()
    {
        InitializeComponent();
    }
 
    public static WaitLoading GetInstance()
    {
        if(waitLoading == null waitLoading.IsDisposed)
        {
             waitLoading = new WaitLoading();
        }
        return waitLoading;
    }

}

        既然调用Close释放掉了对象,那么我用懒汉式单例的时候,如果对象已经被释放了,它就会给我创建一个新的对象,这样应该没错了。但是等我测试的时候,系统依然提示“不能够引用已释放的对象”。突然有点不理解了,既然对象释放了,那么应该就给我创建一个呀,但这里为什么没创建呢?那说明这个对象并不等于null。

        带着这个疑问,我查阅了一下,发现是GC的问题。我这里不细讲GC,我会在之后的博客中慢慢描述我自己理解的GC。我们这里调用对象的Close方法后,对象的确是已经被释放了,但是因为垃圾回收,这个对象没有确定性毁坏,比如我们创建这个对象是用 a 接收的,当a.Close()之后,引用的这个对象已经被释放,但是a这个地址里面存放的依然有数据,这个指向的就是一个已经被处理了的,即disposed了的对象或者其它的数据。所以并不为null,因此访问的时候就会出现“不能够引用已经释放了的对象”的报错提示。

        当然,关于GC绝不是这么简单的,之后我会将GC的标记算法、可达性算法等再写成博客来介绍的。

发布了165 篇原创文章 · 获赞 41 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/qq_41061437/article/details/100120625
今日推荐