在运行时加载,使用和卸载装配 [英] Load, Use and the Unload an Assembly at runtime

查看:96
本文介绍了在运行时加载,使用和卸载装配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在一个项目中,我必须在运行时加载程序集(让它们称为任务),运行该任务,然后能够终止整个程序集,以便可以在不中断主应用程序的情况下替换dll. >
在主应用程序中有许多任务正在运行,有些任务是顺序运行的,而有些则是并行运行的.有时,其中一项或多项任务需要更新,然后重新添加到队列中.当前,我们正在停止整个应用程序,并在处于其他阶段的其他任务之间进行交互,这并不理想.

我已经知道必须将每个程序集加载到单独的AppDomain中,但是事实证明在这些域中加载程序集非常困难,尤其是当我需要实际运行任务并从中接收事件时.我已经研究了这个问题几天,但仍然没有获得有效的概念证明.

我有一个任务接口,其中包括一个运行"和杀死"方法(subs)以及一个任务步骤",完成"和被杀死"事件. ``taskstep''返回一个对象以供稍后缓存,完成整个任务后将触发``complete'',而准备卸载时将触发``killed''.万一它被卡住,整个过程还应该有两个小时的超时,而被终止的事件应该有一个2分钟的超时,这时我希望能够卸载它,迫使任何线程终止(这是什么)无论如何,杀"应该做.每个程序集可能包含多个任务,所有任务都应可装载.

将这些任务作为插件"加载时,我没有问题,但是在尝试同时使用和卸载它们时迷失了方向.如果我必须创建一些精致的包装器,那么就可以了,但是我什至需要吗?

(PS.我希望我可以在c#中做到这一点,但有人告诉我VB是更可取的.如果只有在c#中可行,那么对我来说就更好了,但对我的老板来说不是那么好^ _ ^)

非常感谢
Andy

Hi,

I am working on a project where I have to load assemblies (lets call them tasks) at runtime, run the task and then be able to kill off the whole assembly so that the dll can be replaced without interupting the main application.

There are many of these tasks running within the main application, some run sequentially and some run in parallel. Occasionally one or to of these tasks need to be updated and then re-added to the queue. Currently we are stopping the entire application and interupting the other tasks at whatever stage they are at, which is not ideal.

I have figured out that I will have to load each assembly into a seperate AppDomain, but loading the assemblies in those domains is proving difficult, especially when I need to actually run the tasks and receive events from them. I have been looking into this problem for a couple of days and have still not managed to get a working proof-of-concept.

I have an Interface for the tasks which includes a ''run'' and ''kill'' method (subs) and a ''taskstep'', ''complete'' and ''killed'' event. ''taskstep'' returns an object to be cached later, ''complete'' fires when the whole task is done and ''killed'' fires when it is ready to be unloaded. There should also be a timeout on the whole process of two hours and a timeout of 2 minutes on the killed event incase it gets stuck, at which point I would like to be able to unload it, forcing any threads to terminate (which is what ''kill'' should do anyway). Each assembly may contain several tasks, all of which should loadable be unloadable.

I have no problems loading these tasks as ''plugins'' but am lost when trying to both use them and unload them. If I have to create some elaborate wrapper then so be it but is what I need even possible?

(PS. I wish I could do this in c# but I have been told that VB is preferable. If it is only possible in c# then all the better for me, but not so much for my boss ^_^)

Many thanks
Andy

推荐答案

我已经做过几次这样的事情.就像您说的那样,卸载程序集的唯一方法是抛弃其所在的整个应用程序域.之所以出现这种窍门,是因为应用程序域是相互隔离的(目的是如此),因此您需要将数据与它们之间进行编组.

我想记住的确切方法,但是您需要在每个域中创建一个宿主类,并使它从MarshalByRefObject继承.在您的呼叫(主)域中,将创建一个模拟该代理的代理.因此,该对象需要包含与域通信所需的所有方法和事物.将它们放在所有域共享的界面中.

每个域都可以有自己的单独的包含程序集的基本文件夹,也可以显式加载它们.通过将其指向文件夹进行解析虽然可以帮助加载依赖项.
I''ve done this sort of thing before a few times. As you say, the only way to unload an assembly is to ditch the whole appdomain it''s in. The trick comes because appdomains are isolated from each other (the very purpose) so you need to marshall the data to and from them.

The exact way I''ve done this I''m struggling to remember, but you''ll need to create a host class in each domain and make it inherit from MarshalByRefObject. In your calling (main) domain a proxy is created which mimics this. So this object needs to contain all the methods and things you need to communicate with the domain. Stick those in an interface shared by all domains.

Each domain can have its own seperate base folder containing the assemblies or can have them explicitly loaded. By pointing it at a folder to do resolution though helps with loading dependencies.


为此使用COM对象是非常有趣的解决方案,并且在Windows操作系统中已有相当长的一段时间了.您可以创建过程中或过程外.在应用程序中使用Excel是进程外用法的一个示例(尽管Excel不是最佳示例,因为它是一个交互式过程,因此不适合服务器应用程序).但是这个想法是差不多的.您可以请求一个COM对象,该对象将由COM服务器加载到内存中,然后可以使用.在您的情况下,您开始执行任务.您可以使用事件接收器接收事件,完成后,您可以简单地将其丢弃. COM对象将在池中保留一段时间,并在一段时间后也从内存中丢弃. COM服务器将其保存在池中一段时间​​,以防万一您很快需要另一个.这意味着您无需自己担心.但是为什么要使用它呢?好吧,最有趣的部分可能是您还可以使用事务.这意味着您可以例如使一个文件删除对象.您开始一个新事务,为3个不同的文件创建3个文件,删除com对象,然后提交.然后,仅在可以全部删除3个文件的情况下才删除3个文件.如果无法删除一个,则事务将失败,并且不会删除任何文件. DCOM的另一个不错的功能是可以在另一个系统上创建一个COM对象.甚至这些对象也可以成为事务的一部分,从而使您可以更好地控制整个操作.进行研究可能很有趣.

http://msdn.microsoft.com/en-us/library/aa645736%28v = vs.71%29.aspx [ ^ ]

祝你好运!
Using COM objects for this is a very interesting solution and is part of the windows os for quite some time. You can create in process or out of process. Using Excel in an application is an example of usage of out of process (although Excel is not the best example because it is an interactive process and in that way not suitable for server applications). But the idea is about the same. You can request a COM object which will be loaded into memory by the COM server and can then be used. In your case you start a task. You can use an event sink for receiving events and when you are done you can simply discard it. The COM Object will stay in the pool for a while and after some time it is also discarded from memory. The COM server keeps it in a pool for a while just in case you need another quite soon. This means that you don''t need to worry about it yourself. But why use this? Well, the most interesting part might be that you can also use transactions. Meaning that you can, for example, make a file delete object. You start a new transaction, create 3 file delete com objects for 3 different files and then commit. The 3 files are then only deleted if all 3 can be deleted. If one cannot be deleted, the transaction will fail and none of the files is deleted. Another nice feature is DCOM which makes it possible to create a COM object that is on another system. Even these objects can be part of a transaction giving you great control of the whole operation. It might be interesting enough to investigate.

http://msdn.microsoft.com/en-us/library/aa645736%28v=vs.71%29.aspx[^]

Good luck!


你好,

你有看过反射吗?

几年前,我不得不加载和使用在运行时更改的程序集.

这是我的方法:

Hello,

Have you looked at using reflection?

I few years ago, I had to load and use assemblies that were changing at runtime.

This is how I did it:

string pathToAssembly = Path.Combine(Application.StartupPath, "myAssemby.dll");
object[] parameters = null;
Assembly assembly = Assembly.LoadFile(pathToAssembly);
Type type = assembly.GetType("MyAssembly.Form1");
MethodInfo methodInfo = type.GetMethod("ShowDialog", Type.EmptyTypes);
object instance = Activator.CreateInstance(type);

methodInfo.Invoke(instance, parameters);



瓦莱里.



Valery.


这篇关于在运行时加载,使用和卸载装配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆