11

我想在不停止服务的情况下更新服务器进程的 dll。我怎么做?有点像 asp.net 如何自动拾取放在 bin 文件夹中的新 dll。

4

3 回答 3

22

Asp.Net 使用一种称为影子复制的技术

如果将更新的 dll 复制到应用程序的 bin 子目录中,ASP.NET 运行时会识别出有新代码要执行。由于 ASP.NET 无法将 dll 交换到现有的 AppDomain 中,因此它会启动一个新的 AppDomain。旧的应用程序域是“drain stop”的,即允许现有请求完成执行,一旦它们全部完成,AppDomain 就可以卸载。新的 AppDomain 以新代码开始并开始接受所有新请求。

通常,当 dll 加载到进程中时,进程会锁定 dll,您无法覆盖磁盘上的文件。但是,AppDomains 有一个称为 Shadow Copy 的功能,它允许程序集在磁盘上保持解锁和可替换状态。

运行时初始化 ASP.NET,并为 bin 目录启用卷影复制。AppDomain 会将它需要的任何 dll 从 bin 目录复制到一个临时位置,然后再将 dll 锁定并加载到内存中。Shadow Copy 允许我们在更新期间覆盖 bin 目录中的任何 dll,而无需使 Web 应用程序脱机。

于 2008-10-22T16:32:41.907 回答
2

除了 Gulzar 的回答:

如果您的服务只是直接引用 DLL,您需要重新设计服务以利用 AppDomains 和 ShadowCopy 功能来利用此功能。

我们做这样的事情,服务只是一个外壳/主机进程。所有功能都在需要时加载到单独的应用程序域中。

http://blogs.msdn.com/junfeng/archive/2004/02/09/69919.aspx

于 2008-10-22T16:44:30.197 回答
-2

当进程加载了 dll 后,就无法更改它。

IIS 在不使用时不会将 DLL 加载到内存中(受 Cache 属性影响),我假设 ASP.NET 也是如此。如果您遵循相同的策略,您也可以更新您的 dll。

但是,如果正在使用您的 dll,您应该有办法告诉您的服务器进程卸载所有 dll。

为此,服务器进程必须使用 LoadLibrary 调用加载所有 DLLS,以便在收到要求它这样做的通信时卸载它们。

与服务器进程的通信可以通过创建一个全局可用的命名事件来完成,新程序可以访问该事件并用于向正在运行的进程发出更新即将发生的信号。(您也可以考虑这样做的其他变体)。

于 2008-10-22T17:04:44.180 回答