Search code examples
c#classtimerdynamic-assemblies

Does this class stay created?


I'm dynamically loading an assembly, creating an instance of a class that implements IRegisterable, then calling a registration method with this shortened code:

    public bool RegisterASM(string path)
    {
        Assembly asm = LoadAssembly(path); //helper to load assembly

        if (asm != null)
        {
            var registerableTypes = from t in asm.GetTypes()
                                    where t.IsClass &&
                                    (t.GetInterface("IRegisterable") != null)
                                    select t;

            foreach (Type t in registerableTypes)
            {
                IRegisterable reg = (IRegisterable)asm.CreateInstance(t.FullName, true);
                reg.Register(this);
            }
            return true;
        }
        else
        {
            Console.WriteLine("Assembly not found");
            return false;
        }
   }

And an example of the IRegisterable class:

public class Class1 : IRegisterable
{

    public bool Register(IRegistrationUtilities regHandler)
    {
        Action<Dictionary<string, object>> actionMeathod = TestJob;
        regHandler.RegisterJob(actionMeathod, "Testing", 30000, true);

        Class3 c = new Class3();
        actionMeathod = c.TestJob3;
        regHandler.RegisterJob(actionMeathod, "Test3", 5000, true);
        return true;
    }

    public void TestJob(Dictionary<string, object> vars)
    {
        Console.WriteLine("SleepStart");
        Thread.Sleep(40000);
        Console.WriteLine("SleepEnd");
    }
}

public class Class3
{
    int t = 5;

    public void TestJob3(Dictionary<string, object> vars)
    {
        Console.WriteLine("test 3...{0}", t);
    }
}

When the class registers, it calls a method in the RegistrationHandler that will in turn call a method in the JobScheduler that will create a Threading.Timer with the TimerCallback being the actionMeathod passed in the registration. Besides that, there is no other reference to the IRegisterable class.

My question is, does the class stay in memory since there is a reference to the method or is the class recreated every time the method is called? Or a combination of both?

The reason I ask is that Class1.Register creates an instance of Class3 and passes Class3.TestJob3 as the actionMeathod. When Class3 is created, it sets t=5, which is used in TestJob3. but when the Register method exits, the instance of Class3 is destroyed since it was a local variable. But the timed call to Class3.TestJob3 still has t=5, so is Class3 recreated every time or does it persist?


Solution

  • but when the Register method exits, the instance of Class3 is destroyed since it was a local variable.

    This is incorrect for reference types. Reference objects are allocated on the heap. The local variable c merely points to this object. The garbage collector will destroy the instance at a later time when it determines that the object is not referenced.

    However, the delegate object (Action<Dictionary<string, object>>) has a reference to the Class3 object, so it will not be garbage collected until that delegate object itself can be collected. So the Class3 instance will indeed outlive execution of the Register() method, since it will still be referenced by the delegate after this method returns.

    You can prove this to yourself:

    Class3 c = new Class3();
    actionMeathod = c.TestJob3;
    regHandler.RegisterJob(actionMeathod, "Test3", 5000, true);
    
    // Add this line.
    Console.WriteLine(object.ReferenceEquals(c, actionMeathod.Target));
    

    The output will be "True", indicating that the delegate does indeed have a reference to the same object that c does.