What's Shadow Copying?
我们安装一个应用程序并启动后,我们是无法更新应用程序安装目录中程序集文件的。如果强制替换会提示文件正在使用,如下图所示。
那你可能会问,为什么会无法更新呢?
因为启动应用程序时,CLR会首先创建应用程序域,然后在应用程序域中加载程序集并将其锁定。因此在卸载程序集之前是无法更新文件的。而卸载程序集的唯一办法就是卸载加载程序集的应用程序域。
到这里,你可能会好奇,为什么在开发ASP.NET网站时,我们却可以持续编译项目,而不会报这个提示呢?毕竟我们是从编译目录起的站点啊,而且我们每次编译会更新程序集的啊?!!!
这个疑问的答案就是我们本文的主题——Shadow Copying(卷影复制)。
Shadow copying enables assemblies that are used in an application domain to be updated without unloading the application domain. This is particularly useful for applications that must be available continuously, such as ASP.NET sites.
卷影复制机制允许我们更新正在被应用程序域中使用的程序集而不需要卸载应用程序域。这个机制对必须保持持续可用的应用程序来说特别有用,比如ASP.NET网站开发。
ASP.NET使用了卷影复制这种技术,允许资源保持连续可用,而不会干扰AppDomain中的代码执行。
在ASP.NET应用程序启动时,它会将应用程序路径中的程序集文件复制到另外一个路径,然后从另外一个路径加载程序集并锁定。这样原来路径的程序集文件就不会锁定,从而可以更新。
Where the file copied to?
Shadow Cope的文件存储在C盘的Temporary ASP.NET Files
目录,可能在C:Users{UserName}AppDataLocalTemp
下,也可能在C:WindowsMicrosoft.NETFramework
下。找不到可以网上下载search everything工具搜索。
Which files are shadow copied?
默认来说,应用程序目录及其子目录中的程序集会被Shadow Copy。但位于GAC(全局应用程序集缓存)中的程序集不会被复制。
The disadvantage of Shadow Copying
当ASP.NET 应用程序有很多资源和程序集时,它的启动将会耗时很长,而这也正是由于Shadow Copying导致的。
Disabling shadow copying
即然Shadow Copying会导致大体量的ASP.NET应用启动很慢,那有没有办法改进呢?
第一种就是关闭Shadow Copying:将<hostingEnvironment shadowCopyBinAsmblies ="false"/>
配置节点添加到Web.Config文件下的System.Web下即可。
第二种就是手动指定CLR的应用程序基础子目录,以便在加载程序集时进行搜索:
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Bin;BinTestPlugIn" />
</assemblyBinding>
probing节点下的privatePath中指定的子目录是不会进行Shadow Copying的。
Reference
What is the “Temporary ASP.NET Files” folder for?
Shadow Copying Assemblies
重温.NET下Assembly的加载过程
ASP.NET, APPDOMAINS, AND SHADOW-COPYING