Assembly asy = Assembly.Load(System.AppDomain.CurrentDomain.BaseDirectory + nmSpace + ".dll"); Type type = asy.GetType(classMap); object obj = Activator.CreateInstance(type); MethodInfo mi = type.GetMethod("Start"); mi.Invoke(obj, new object[] { thd.IOID, thd.ConnectionName });
这段代码 Assembly.Load方法加载程序集,是为了,我可以动态的修改程序集的内容, 但是现在问题是,这样修改,Assembly的缓存过大,占用服务器的内存过高,这个有没有办法,2全其美,既可以动态的修改,并可以保证服务器占用内存不要那么高.
求大神解答,谢谢!
你这样加载后assembly不会释放的,你正确的做法是加载assembly后就完了,后面要用的时候再直接从缓存的assembly中去拿type及你后续的事情。
当然由于还是前面提到的assembly加载后的不释放,长时间使用这种热插拔方式进行修改还是会导致内存过高甚至outofmemory,但需要的时间很长(前提是你修改的并不很频繁)。
如果需要规避需要额外起appdomian,通过appdomain的卸载把在其appdomian中加载的assembly进行卸载,不过实现有点啰嗦,而且一般情况下也不至于如此。
我尝试用了appdomian,但是就不能动态去修改程序集。还是很感谢。
@Color_male_goat: 程序集肯定不可能修改了,按照你的这种实现是卸载此appdomian后再创建后再在这个appdomian中加载新的程序集。
@Color_male_goat: 你挂载一个FileSystemWatcher去监控这个文件的变化,然后根据变化去触发你的重新加载操作。
@Daniel Cai: 嗯嗯,我试试吧,这个程序最主要的是需要一直运行不能停止,这是第一点,第二点就是,有时候,需要及时更新程序集。
@Color_male_goat: 如果你这个程序不能停这就是一个错误的设计,谁来保证这玩意不出点问题?一般更新时half on half off这种很常见,不可能是那种极端的在开着的飞机上换引擎那么复杂的场景。
@Daniel Cai: 不是,这个,程序不是说不能停,尽量的不要停,除非出现大问题,不然,就都只用,更新dll。就来更新程序。
@Color_male_goat: 你用appdomian可以达到这种效果,和iis的定时回收类似。大体流程是当你default appdomain监控到文件变更,然后新建appdomain,执行你相关加载逻辑,一旦完成后即将请求转移到新的appdomain中执行,然后卸载老的appdomain(iis中是做了定时,如果超过一定时间还在老的那块执行则被强行终止)。
关于高可用,简单的话可以前面加一负载均衡就完了。复杂点的可以类似像dubbo这种分布式rpc框架,通过服务端注册,应用端订阅获取服务地址,当一旦某个节点不可用,应用端可立即感知并将其排除到服务地址列表外。
@Daniel Cai: 谢谢你了。高可用,这个做了。
Assembly asy = Assembly.Load(System.AppDomain.CurrentDomain.BaseDirectory + nmSpace + ".dll");
这个方法传的不是dll路径,这里会报错吧,正常Assembly.Load不会占用很大的内存,看起来是你用的方法每次调用都加载了一次assembly,改成成员变量只加载一次试试。
System.AppDomain.CurrentDomain.BaseDirectory + nmSpace + ".dll") 这个就是路径 。。。。。。