0

我正在动态加载程序集,创建实现的类的实例IRegisterable,然后使用以下缩短的代码调用注册方法:

    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;
        }
   }

还有一个IRegisterable类的例子:

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);
    }
}

当类注册时,它会调用 中的一个方法,RegistrationHandler然后调用该方法中的一个方法,该方法JobScheduler将创建一个Threading.Timer在注册TimerCallbackactionMeathod传递的对象。除此之外,没有其他对该IRegisterable类的引用。

我的问题是,类是否保留在内存中,因为有对该方法的引用,还是每次调用该方法时都会重新创建该类?还是两者兼而有之?

我问的原因是Class1.Register创建一个实例Class3Class3.TestJob3作为actionMeathod. 创建Class3时,它会设置t=5,用于TestJob3. 但是当Register方法退出时,实例Class3被销毁,因为它是一个局部变量。但是定时调用Class3.TestJob3仍然有t=5,所以Class3每次都重新创建还是持续存在?

4

2 回答 2

0

但是当Register方法退出时,实例Class3被销毁,因为它是一个局部变量。

这对于引用类型是不正确的。引用对象在堆上分配。局部变量c仅仅指向这个对象。垃圾收集器将在稍后确定该对象未被引用时销毁该实例。

但是,委托对象 ( Action<Dictionary<string, object>>) 具有对该Class3对象的引用,因此在该委托对象本身可以被收集之前,它不会被垃圾收集。因此,Class3实例确实会比方法的执行时间更长Register(),因为在此方法返回后,它仍会被委托引用。

你可以向自己证明这一点:

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

// Add this line.
Console.WriteLine(object.ReferenceEquals(c, actionMeathod.Target));

输出将为“True”,表示委托确实具有对相同对象的引用c

于 2014-08-20T17:04:06.613 回答
0

这取决于您的IRegistrationUtilities.RegisterJob方法的实现。例如,如果它将您TestJob的操作放入私有变量中,您Class3将保持活动状态,直到IRegistrationUtilities垃圾收集器不处理实例。

另外请注意,即使RegisterJob什么都不做,Class3由于 .NET 垃圾收集器的不确定性,您可能不会立即处理(或者甚至与您的应用程序具有相同的生命周期)。

于 2014-08-20T17:10:15.513 回答