首页 新闻 搜索 专区 学院

反射加载程序集 Assembly缓存过大

0
悬赏园豆:100 [已解决问题] 解决于 2016-11-17 10:57
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全其美,既可以动态的修改,并可以保证服务器占用内存不要那么高.

      求大神解答,谢谢!

Color_male_goat的主页 Color_male_goat | 初学一级 | 园豆:10
提问于:2016-11-16 13:43
< >
分享
最佳答案
1

你这样加载后assembly不会释放的,你正确的做法是加载assembly后就完了,后面要用的时候再直接从缓存的assembly中去拿type及你后续的事情。

当然由于还是前面提到的assembly加载后的不释放,长时间使用这种热插拔方式进行修改还是会导致内存过高甚至outofmemory,但需要的时间很长(前提是你修改的并不很频繁)。

如果需要规避需要额外起appdomian,通过appdomain的卸载把在其appdomian中加载的assembly进行卸载,不过实现有点啰嗦,而且一般情况下也不至于如此。

收获园豆:100
Daniel Cai | 专家六级 |园豆:10374 | 2016-11-16 13:59

我尝试用了appdomian,但是就不能动态去修改程序集。还是很感谢。

Color_male_goat | 园豆:10 (初学一级) | 2016-11-16 14:10

@Color_male_goat: 程序集肯定不可能修改了,按照你的这种实现是卸载此appdomian后再创建后再在这个appdomian中加载新的程序集。

Daniel Cai | 园豆:10374 (专家六级) | 2016-11-16 14:27

@Color_male_goat: 你挂载一个FileSystemWatcher去监控这个文件的变化,然后根据变化去触发你的重新加载操作。

Daniel Cai | 园豆:10374 (专家六级) | 2016-11-16 14:30

@Daniel Cai: 嗯嗯,我试试吧,这个程序最主要的是需要一直运行不能停止,这是第一点,第二点就是,有时候,需要及时更新程序集。

Color_male_goat | 园豆:10 (初学一级) | 2016-11-16 14:35

@Color_male_goat: 如果你这个程序不能停这就是一个错误的设计,谁来保证这玩意不出点问题?一般更新时half on half off这种很常见,不可能是那种极端的在开着的飞机上换引擎那么复杂的场景。

Daniel Cai | 园豆:10374 (专家六级) | 2016-11-16 14:39

@Daniel Cai: 不是,这个,程序不是说不能停,尽量的不要停,除非出现大问题,不然,就都只用,更新dll。就来更新程序。

Color_male_goat | 园豆:10 (初学一级) | 2016-11-16 14:44

@Color_male_goat: 你用appdomian可以达到这种效果,和iis的定时回收类似。大体流程是当你default appdomain监控到文件变更,然后新建appdomain,执行你相关加载逻辑,一旦完成后即将请求转移到新的appdomain中执行,然后卸载老的appdomain(iis中是做了定时,如果超过一定时间还在老的那块执行则被强行终止)。

关于高可用,简单的话可以前面加一负载均衡就完了。复杂点的可以类似像dubbo这种分布式rpc框架,通过服务端注册,应用端订阅获取服务地址,当一旦某个节点不可用,应用端可立即感知并将其排除到服务地址列表外。

Daniel Cai | 园豆:10374 (专家六级) | 2016-11-16 16:50

@Daniel Cai: 谢谢你了。高可用,这个做了。

Color_male_goat | 园豆:10 (初学一级) | 2016-11-17 10:56
其他回答(1)
0

Assembly asy = Assembly.Load(System.AppDomain.CurrentDomain.BaseDirectory + nmSpace + ".dll");

这个方法传的不是dll路径,这里会报错吧,正常Assembly.Load不会占用很大的内存,看起来是你用的方法每次调用都加载了一次assembly,改成成员变量只加载一次试试。

ArthurLi | 园豆:686 (小虾三级) | 2016-11-16 14:02

System.AppDomain.CurrentDomain.BaseDirectory + nmSpace + ".dll")   这个就是路径 。。。。。。

支持(0) 反对(0) Color_male_goat | 园豆:10 (初学一级) | 2016-11-16 14:11
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册