当垃圾收集在运行时,析构函数如何调用[.NET]?

abh*_*vce 1 .net c# garbage-collection

我是用的垃圾收集器实验和发现了奇怪的计数iCntdestructor电话.这是守则: -

public class MyClass
{
    static long iCnt;
    public MyClass()
    {
        iCnt++;
    }

    ~MyClass()
    {
        iCnt--;
    }
    static public string ObjectCount
    {
        get
        {
            return iCnt.ToString();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

下面的代码是创建对象,删除对象(通过分配去参考null)和显式调用GC.Collect().我已经让所有它具有运表Timerinterval = 100,计时器显示的当前计数iCnt.

public partial class Form1 : Form
{
    MyClass[] Objs;
    public Form1()
    {
        InitializeComponent();
    }

    private void btnCreateObjects_Click(object sender, EventArgs e)
    {
        Objs = new MyClass[1000];
        for (int i = 0; i < 1000; i++)
        {
            Objs[i] = new MyClass();
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        label2.Text = MyClass.ObjectCount;
    }
    private void btnDeleteObjects_Click(object sender, EventArgs e)
    {
        for (int i = 0; i < 1000; i++)
        {
            Objs[i] = null;
        }
    }

    private void btnInvokeGC_Click(object sender, EventArgs e)
    {
        GC.Collect();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在创建对象,直到自动调用垃圾收集器(对我来说,它需要24次点击).再次重复此动作.

我看到这iCnt<1000.这让我混淆了析构函数在这种情况下如何调用.当iCnt<1000时,点击删除对象的删除对象Objs[1000].然后调用GC.Collect()计数iCnt<0(非常奇怪).

任何人都可以解释我这种行为.提前致谢.

Han*_*ant 5

这是一个非常经典的线程错误.析构函数在终结器线程上运行,与递增计数的线程异步.您需要使用Interlocked.Increment()和Decrement()来安全地执行此操作.或者使用lock关键字.