【发布时间】: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