【问题标题】:Assembly remains after unloading appdomain卸载 appdomain 后程序集仍然存在
【发布时间】:2021-09-11 17:41:21
【问题描述】:

我有一个程序,它创建AppDomain,在其中加载程序集prelude,然后卸载AppDomain。最后程序列出来自默认 appdomain 的程序集。它是程序的简化版本。在下一个版本中,prelude.dll 将在运行时更改并使用 appdomain 持续执行/卸载。

namespace appdomaintest
{

    class Program
    {
        static void log_assemblies(AppDomain domain)
        {
            foreach (var item in domain.GetAssemblies())
            {
                Console.WriteLine($"{domain.FriendlyName} : {item.FullName}");
            }
        }
        static void Main(string[] args)
        {
            {
                var prelude_domain = AppDomain.CreateDomain("PreludeDomain#1", null, null);
                var asm = prelude_domain.Load(new System.Reflection.AssemblyName("prelude"));
                var myint = prelude_domain.CreateInstanceAndUnwrap("prelude", "prelude.MyInt");
                myint.GetType().GetMethod("show").Invoke(myint, new object[0]);
                AppDomain.Unload(prelude_domain);
                Console.WriteLine("AppDomain was unloaded");
            }
            log_assemblies(AppDomain.CurrentDomain);
        }
    }
}  

这里是prelude.dll的内容

public class MyInt : MarshalByRefObject
{
    public MyInt()
    {
        Console.WriteLine($"MyInt was constructed in {AppDomain.CurrentDomain.FriendlyName}");
    }
    public void show()
    {
        Console.WriteLine($"show in {AppDomain.CurrentDomain.FriendlyName}");
    }
}

这是程序的输出:

MyInt was constructed in PreludeDomain#1
show in PreludeDomain#1
AppDomain was unloaded
appdomaintest.exe : mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
appdomaintest.exe : appdomaintest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
appdomaintest.exe : prelude, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null

不幸的是,我发现我的默认 appdomain 包含 prelude.dll 程序集。据我了解,它一直持续到我的程序执行结束。有什么方法可以防止将其加载到默认的应用程序域?在未来的版本中,prelude.dll 将被重复加载/卸载(其元数据也将被修改)。这就是为什么这种行为不适合我的目的。

在我看来,创建代理对象可能会导致将元数据加载到默认域。但是我怎样才能卸载它们呢?

【问题讨论】:

  • 使用 IPC,我已将它用于从数据库编译运行时剃须刀页面。然后,在单独的进程在 RAM 上变得太大之后 - 杀死它,重新开始。这是目前唯一的方法。
  • @eocron 这是重型机械。本机进程的创建/中断/互连成本很高。在我的情况下,加载动态程序集的频率非常大。
  • 没有人给你保证。见这里 - docs.microsoft.com/en-us/dotnet/framework/app-domains/… 您要么采用流程方法,要么考虑改变您通过库集成第三方功能的方法(将其切换为服务)。您不需要一直启动本机进程,只需启动它,加载这个东西,卸载它,然后在达到内存或计数限制时关闭进程。

标签: c# .net reflection appdomain


【解决方案1】:

它会保留,是的。没有办法解决它,因为这是不可能的,微软在这里声明:https://docs.microsoft.com/en-us/dotnet/framework/app-domains/how-to-unload-an-application-domain

使用与另一个进程的进程间通信。您可以启动进程并在其中加载任何内容,直到它变得臃肿,然后您只需将其杀死并重新开始。

您从中获得的一个好处 - 没有人会在您的应用程序意外调用此库中不安全的内容时崩溃。

【讨论】:

  • 您的意思是域中立程序集吗?但是为什么我的程序集是域中立的?
猜你喜欢
  • 2012-11-06
  • 2010-09-12
  • 2011-01-09
  • 1970-01-01
  • 2023-01-14
  • 1970-01-01
  • 2011-04-09
  • 2019-01-22
  • 2021-05-07
相关资源
最近更新 更多