0

This is my code,the results and expected results. Why alive = true instead of false on second line?

Results:

weakRef.Target is alive = True, expected true because inst keep a hold on SomeClass.
weakRef.Target is alive = True, expected false, because there is no more ref on SomeClass.

Code:

public class SomeClass
{
    public void DoSomething() { }
}

public static class GcHelper
{
    public static void Collect()
    {
        // OK surely overkill but just to make sure. I will reduce it when everyting will be understood.
        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
        GC.WaitForPendingFinalizers();

        GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true);
        GC.WaitForPendingFinalizers();
    }
}

[TestMethod]
public void TestLifeOfObject()
{
    Action callback;

    var inst = new SomeClass();
    var weakRef = new WeakReference<Action>(inst.DoSomething);

    GcHelper.Collect();
    Debug.WriteLine($"weakRef.Target is alive = {weakRef.TryGetTarget(out callback)}, expected true because inst keep a hold on SomeClass.");

    callback = null;
    inst = null;
    GcHelper.Collect();
    Debug.WriteLine($"weakRef.Target is alive = {weakRef.TryGetTarget(out callback)}, expected false, because there is no more ref on SomeClass.");
}
Eric Ouellet
  • 10,996
  • 11
  • 84
  • 119
  • is `new WeakReference(inst.DoSomething);` a typo? Did you mean to write `new WeakReference(inst);`? – jt000 Oct 26 '22 at 19:41
  • Adding `await Task.Delay(1);` before `GcHelper.Collect();` is fixing the issue. From this by not knowing the reason I think GC is not aware instantly (or in a synchronous way) when an object is dereferenced. – Eldar Oct 26 '22 at 20:00
  • @jt000, My intention was what I wrote. The only thing is "Action callback;" has no reason to be there actually. – Eric Ouellet Oct 27 '22 at 01:26
  • @Eldar, I'm a little bit happy to know it but I would really like to understand the full reason why I have this behavior. I actually try to write a SmartWeakEvent class which does not have the expected behavior and I suspect something wrong related with the GC and or the class ConditionalWeakTable (my next question when this one will be clearly understood). Perhaps there is a piece of the puzzle that is missing and that's what i'm looking for. – Eric Ouellet Oct 27 '22 at 01:29
  • 1
    Try in both debug and release builds. I'm guessing `inst = null;` is optimized away so the object is not actually released until the end of the function. You must test GC collecting from outside this function, not while still in it. – Charlieface Oct 27 '22 at 01:38
  • @Charlieface, Thanks a lot. I think you are 100% right !!!!! – Eric Ouellet Oct 27 '22 at 02:20
  • @Charlieface, If you have some time, I have a new question where I'm not sure I will ever get a solution to it: https://stackoverflow.com/questions/74216108/conditionalweaktable-gc-collect-behavior-why-it-does-not-operate-as-expecte – Eric Ouellet Oct 27 '22 at 13:42

0 Answers0