C# 多个AppDomain泄漏某些对象

C# 多个AppDomain泄漏某些对象,c#,.net-3.5,appdomain,C#,.net 3.5,Appdomain,我正在尝试创建一个插件系统。现在,我有一个系统可以在运行时加载和卸载一些动态库 我这样创建AppDomain: AppDomain是一个private成员变量。 RemoteLoader是一个私有成员变量 AppDomainSetup setup = new AppDomainSetup { ApplicationName = assemblyName, ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, Co

我正在尝试创建一个插件系统。现在,我有一个系统可以在运行时加载和卸载一些动态库

我这样创建AppDomain:
AppDomain
是一个
private
成员变量。
RemoteLoader
是一个私有成员变量

AppDomainSetup setup = new AppDomainSetup
{
    ApplicationName = assemblyName,
    ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
    ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
};

AppDomain = AppDomain.CreateDomain(domainName, null, setup);
remoteLoader = (RemoteLoader)AppDomain.CreateInstanceAndUnwrap(assemblyName, typeName);
RemoteLoader
保留可用
程序集的列表,可以创建对象和查找对象。
已正确创建
AppDomain
。当我卸载时,我可以看到
AppDomain
从VisualStudio上的模块列表中消失

我正在运行Jetbrains dotMemory查找内存泄漏

我现在的测试是:

  • 加载服务,不带任何插件
  • 快照
  • 加载一些插件
  • 让插件工作一段时间
  • 卸载插件(卸载整个AppDomain)
  • 快照
当我比较这两个快照时,我可以看到一些永远不会消失的对象

一些
字符串
包含以下文本:

  • STEP_Service.Contract.ModuleBase,STEP_Service.Contract,版本=1.0.0.0,区域性=中性,PublicKeyToken=null
  • “/6ceffbca_d8b4_43be_39b8cb09ef37/s5bbue3ddey9xxfuevnmvmv9_158.rem”
  • “c6360995_32bd_46d9_b83b_3fbac3c58c6a/w1ntjmpe4s+1zp1rkmrio_dy_141.rem”
我不知道发生了什么事。密钥保留路径向我显示: [

堆栈跟踪:

一些
RuntimeMethodInfo
正在泄漏:

其他对象,如:

卸载函数或任何位置都不会引发异常

我的
Dispose
方法调用定义如下的
Unload

/// <summary>
/// Unloads the plugins
/// </summary>
public void Unload()
{
    if (AppDomain == null)
        throw new NullReferenceException(nameof(AppDomain));

    AppDomain.Unload(AppDomain);
    remoteLoader.Dispose();
    AppDomain = null;
    remoteLoader = null;
}
//
///卸载插件
/// 
公众假期
{
if(AppDomain==null)
抛出新的NullReferenceException(nameof(AppDomain));
卸载(AppDomain);
remoteLoader.Dispose();
AppDomain=null;
remoteLoader=null;
}
我知道我没有提供太多的代码,但我真的不知道我需要给出什么样的代码。 如果丢失了什么,请向我索取

每个
都是从
MarshallByRefObject
派生的,为了测试,我将许多字段标记为
不可序列化

根据我的概念,当我调用
AppDomain类的
static
方法
Unload
时,必须释放AppDomain中的所有内容

编辑
在执行我的服务几分钟后,我可以看到以下对象:

看起来CrossAppDomainData和其他对象(由它自己持有)正在增长。该对象位于GC的第2代

编辑
一小时后,我可以看到2794个类型为
CrossAppDomainData
的新对象,以及它所持有的一些其他对象

  • 交叉应用域数据
  • 交叉应用域接收器
  • Int64

编辑
几个小时后,我可以看到大约32k个CrossAppDomainSink、CrossAppDomainData和Int64对象。我的服务内存从8k增长到17k

编辑
我发现了问题,但不知道为什么会发生这种情况。
为了发现问题,我逐步重新创建了服务。
当我多次加载/卸载appdomains时,一切都很好。所有内容都已正确释放,内存正常。 但是,在下一步,即在另一个应用程序上加载dll,以便具有卸载、更新和再次加载的功能时,出现了一些泄漏

换句话说,我的实际情况是:

  • 在另一个AppDomain上加载核心DLL的服务
  • 核心DLL可以在运行时加载插件
  • 核心DLL可以在运行时更改
    • FileSystemWatcher可以监视文件夹中CoreDLL上的更改。发生这种情况时,服务会在所有工作完成后卸载CoreDLL,加载新的CoreDLL,然后重新开始工作
加载的dll(CoreDLL)完成加载插件、查看插件文件夹等艰巨工作。该服务的存在只是为了让CoreDLL拥有自己的更新能力


那么…为什么前面提到的对象正在泄漏?调用是由CoreDLL进行的,而不是由服务进行的。

mscorlib
始终是加载域中立的,这意味着所有应用程序域共享相同的
mscorlib
。您的应用程序域确实使用了
mscorlib
(因为它只是所有人的核心组件)。许多类型的
mscorlib
都是可序列化的,因此对象将从您的自定义应用程序域封送到默认应用程序域。字符串的标识很弱-它们可以跨所有应用程序域直接访问。您是否有特殊问题或怀疑内存泄漏?@dymanoid我有内存泄漏。正如您在屏幕截图上看到的,t他会向我展示正在创建的
字符串
和其他对象,如
RuntimeMethodInfo
ParameterInfo
。但当我运行第三个或更多快照并进行比较时,这些对象仍然存在。这些字符串是一些程序集名称和其他内容(在文章中我给出了一些示例)这本身不是内存泄漏。运行时总是会创建一些系统对象,如
RuntimeMethodInfo
,并使其保持活动状态,而您无法控制这些对象。如果没有泄漏的用户对象,就没有内存泄漏。@dymanoid我明白了。但为什么我的内存会不断增加,即使dotMemory没有显示任何对象呢由我来处理?只是字符串、weakreference、crossappdomainsink不断增长。你有什么问题吗?你的内存不足吗?这些都是兆字节还是几千字节?GC不会尽快收集垃圾。它使用启发式和GC生成来确定何时收集。