我想在单独的应用程序域中动态卸载程序集,但它不起作用

Posted

技术标签:

【中文标题】我想在单独的应用程序域中动态卸载程序集,但它不起作用【英文标题】:I want to dynamically unload an assembly in a separate app domain and it does not work 【发布时间】:2016-09-01 19:10:09 【问题描述】:

我想使用 AppDomain 加载和卸载程序集,但它不起作用。 这是我想出的最简单的例子。

using System;
using System.Reflection;

namespace DomainTest

    class Program
    
        static void Main(string[] args)
        
            AppDomain _newDomain;
            var setup = new AppDomainSetup();
            setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
            setup.ApplicationName = "Isolator";

            _newDomain = AppDomain.CreateDomain("Isolation:" + Guid.NewGuid(),
               null, setup);

            Console.WriteLine("-----------------Before Domain created");
            ShowLoadedAssemblies();

            _newDomain.Load("WorkerTest");
            Console.WriteLine("---------------------After Load");
            ShowLoadedAssemblies();

            AppDomain.Unload(_newDomain);
            Console.WriteLine("--------------------After Unload");
            ShowLoadedAssemblies();

            Console.ReadLine();

        

        public static void ShowLoadedAssemblies()
        
            AppDomain currentDomain = AppDomain.CurrentDomain;
            //Make an array for the list of assemblies.
            Assembly[] assems = currentDomain.GetAssemblies();

            //List the assemblies in the current application domain.
            Console.WriteLine("Currently loaded Assemblies:");
            foreach (Assembly assem in assems)
                Console.WriteLine(assem.ToString());
        
    

为简单起见,WorkerTest 程序集是一个空程序集 除了标准的 Microsoft.CSharp 和 System.Dll 之外,没有任何参考

namespace WorkerTest

    public class Worker
    

    

这个例子有一个带有 Main() 方法的 Program 类,我在其中创建了一个新的 AppDomain (_newDomain) 并将一个 WorkerTest.DLL 程序集加载到其中。之后我卸载 _newDomain 并期望 WorkerTest.DLL 与它一起卸载,但它没有发生。下面您可以看到程序输出显示了加载之前、将 WorkerTest 加载到 _newDomain 之后以及卸载 _newDomain 之后的所有加载程序集。 WorkerTest.DLL 仍然被加载。 谁能告诉我为什么它不起作用?

 -----------------Before Domain created
Currently loaded Assemblies:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Microsoft.VisualStudio.HostingProcess.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualStudio.Debugger.Runtime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
vshost32, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
DomainTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
---------------------After Load
Currently loaded Assemblies:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Microsoft.VisualStudio.HostingProcess.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualStudio.Debugger.Runtime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
vshost32, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
DomainTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
WorkerTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
--------------------After Unload
Currently loaded Assemblies:
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Microsoft.VisualStudio.HostingProcess.Utilities, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualStudio.HostingProcess.Utilities.Sync, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.VisualStudio.Debugger.Runtime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
vshost32, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
DomainTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
WorkerTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

【问题讨论】:

看看这篇文章是否有帮助 - west-wind.com/presentations/dynamicCode/DynamicCode.htm 在下面的 C# load and unload an assembly using AppDomain 上进行谷歌搜索 【参考方案1】:

我认为问题在于这个_newDomain.Load("WorkerTest");Assembly 对象返回到当前应用程序域。由于Assembly 包括对所有元信息的访问,因此它也必须将程序集实际加载到当前域。

要将程序集正确加载到新域中,应仅通过该新域中的代码来完成。或者,如果您只需要创建一个对象的实例 - Loading DLLs into a separate AppDomain

【讨论】:

我按照您的建议寻找了一种在新域中单独加载程序集的方法,但找不到任何有关如何执行此操作的示例。你能给我指出正确的方向吗? ***.com/questions/2008691/…,基本上你需要确保 Assembly.Load 发生在新的 App 域中,并且你永远不会从该程序集中将类型返回到原始域。 我尝试了您建议的示例,但它对我不起作用。问题是,为了在 CreateInstanceAndUnwrap 方法中指定程序集全名和类型全名,我需要引用父域中的程序集。而此刻,当我调用这个 CreateInstanceAndUnwrap 方法时,父域会加载这个程序集。我什至创建了第三个程序集来保存接口定义,它也没有帮助。我在这里错过了什么? 为什么?将加载其他程序集的代码应该在您的 Program 类(或它的同级)中 - 将它加载到两个 appdomains 绝对安全(并且肯定会加载到当前 appdomain :)) 可能我们彼此不了解。使用代理加载其他程序集的代码在我的 Program 类中。为了调用这个方法: WorkerTest.IWorker proxy = (WorkerTest.IWorker)_newDomain.CreateInstanceAndUnwrap( typeof(WorkerTest.Worker).Assembly.FullName, typeof(WorkerTest.Worker).FullName);我必须在父域中引用我想在子域中运行的程序集。此引用导致程序集被加载到父域中,并且在我卸载子域时未卸载。包含此程序集的文件仍处于锁定状态。

以上是关于我想在单独的应用程序域中动态卸载程序集,但它不起作用的主要内容,如果未能解决你的问题,请参考以下文章

我想在 recyclerview 中显示编辑文本数据,但它不起作用

我想在 android 应用程序中发布 geosever 层,使用 arcgis SDK,我已经完成了代码但它不起作用,请告诉我我做错了啥?

创建新的 React 应用程序时出现此错误。也尝试了卸载命令,但它不起作用

反应问题:我在上传文件时尝试了文件数据集的状态,但它不起作用

完整的动态加载卸载程序集的解决方案

我想在使用 kotlin 协程的 android 超时后取消一个函数,但它不起作用