I was experimenting with garbage collector and found strange count iCnt on destructor call.
Here is the Code:-
public class MyClass
{
static long iCnt;
public MyClass()
{
iCnt++;
}
~MyClass()
{
iCnt--;
}
static public string ObjectCount
{
get
{
return iCnt.ToString();
}
}
}
Below code is to create objects, delete objects(De-refernce by assigning to null) and explicitly call GC.Collect().
I have having all it in a Win Form which has Timer of interval = 100, timer show the current count of 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();
}
}
Now create the object until the garbage collector is called automatically(for me it took 24 clicks). Again repeat this action.
I saw this iCnt < 1000. which keeps me confusing how the destructor called in this scenario.
when iCnt < 1000, click on delete object which deference the Objs[1000]. Then call GC.Collect() which makes count of iCnt < 0 (very strange).
Can anybody explain me this behavior. Thanks in advance.
This is a pretty classic threading bug. The destructor runs on the finalizer thread, asynchronously from the thread that increments the count. You need to use Interlocked.Increment() and Decrement() to do this safely. Or use the lock keyword.