Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Appdomain问题_C#_.net - Fatal编程技术网

C# Appdomain问题

C# Appdomain问题,c#,.net,C#,.net,在过去的几天里,我一直在努力解决appdomain的问题。 我创建了一个运行插件的小型windows服务。它的工作方式是,每个插件都是一个dll,使用“CreateInstanceAndUnwrap”将其加载到自己单独的appdomain中,我保留对appdomain的引用,一旦插件完成,我关闭了为该插件创建的appdomain。我正在使用shadow copy来允许插件在框架中运行时进行更新。好的,到目前为止一切正常。它已经完美地运行了6个月,直到上周我决定将框架的核心功能也放入一个单独的DL

在过去的几天里,我一直在努力解决appdomain的问题。 我创建了一个运行插件的小型windows服务。它的工作方式是,每个插件都是一个dll,使用“CreateInstanceAndUnwrap”将其加载到自己单独的appdomain中,我保留对appdomain的引用,一旦插件完成,我关闭了为该插件创建的appdomain。我正在使用shadow copy来允许插件在框架中运行时进行更新。好的,到目前为止一切正常。它已经完美地运行了6个月,直到上周我决定将框架的核心功能也放入一个单独的DLL中,并在一个单独的appdomain中执行该DLL。因此,它现在的工作方式是:

Windows服务启动。核心dll使用CreateInstanceAndUnwrap加载和执行,CreateInstanceAndUnwrap负责在各自的应用程序域中运行插件 (使用CreateInstance和..)

我有两个不同的装配位置: Bin文件夹(windows服务的Bin仅包含服务使用的DLL) 核心DLL文件夹(将核心DLL放在此处) References文件夹(此处会删除任何引用) 插件文件夹(插件被放在这里)

我通过连接到每个appdomain的onassemblyresolve处理程序来解析任何未找到的dll。 这意味着DLL可以通过网络从中加载

现在的问题是windows服务运行了一天,内存高达1.5G。 我创建了一个内存转储,似乎加载的模块在整个1.5G中只有100MB,所以我不知道所有这些内存都将流向何处。使用debugdiag,我看到了堆碎片警报,但我不知道应该从哪里开始诊断该问题。 通常,当框架运行一天时,它会消耗大约1亿美元。此外,这与插件也没有关系,因为当我回滚对框架所做的更改时,memroy的使用与以前一样正常。 当我为插件创建appdomains时,我将appdomain的basePath和bin路径切换到CORE和References文件夹,这些文件夹中包含大多数DLL,希望程序集解析的调用频率降低

我查看了fusion日志,还阅读了更多关于加载上下文的内容,如default、from和none,但我不确定这是否是正确的路径

有什么想法吗?

我认为:

当我决定将框架的核心功能放入 分离DLL并在单独的appdomain中执行该DLL 目前的工作方式是:

Windows服务启动。核心dll使用加载和执行 CreateInstanceAndUnwrap负责运行 插件在各自独立的AppDomain中(使用CreateInstanceand.)

可能与此有冲突:

如果对T1类型的对象的方法M进行早期绑定调用 这是CreateInstanceAndUnwrap返回的,该方法生成 对程序集C中T2类型对象的方法的早期绑定调用 除了当前程序集或包含T1的程序集, 程序集C已加载到当前应用程序域中。这批货 即使对T1.M()的早期绑定调用是在 动态方法,或在其他动态生成的代码中。如果 当前域是默认域,无法卸载程序集C 直到过程结束


在这种情况下,您可能可以使用反射来执行“适当”调用,以消除早期绑定。

我使用一个接口来获取第二个appdomain的代理,最近出现了一个错误,该错误是由于著名的“类型异常的无效转换”导致的因此,我将返回强制转换改为动态类型:D我知道这不是解决问题的好方法,但它解决了强制转换问题。我猜接口dll的多个版本正在加载到调用的appdomain中,这就是为什么它会给出类型强制转换异常。我创建了主appdomain和插件appdomains使用createinstanceandunwrap.for resolve Assembly event我使用“LoadFrom”我将进一步调查是否发生了这种情况,但是当我调试windows服务时,我没有看到加载任何重复的DLL,或者从插件加载带有DLL的主appdomain。看起来一切都很好,即使我放弃了运行1.5G的服务,debugdiag也没有显示出任何迹象。加载模块=100米!文档还说:“即使对T1.M()的早期绑定调用是在DynamicMethod的主体中或在其他动态生成的cod中进行的,也会发生这种加载”。因此,这意味着使用反射也可能不起作用。(如果是这样的话)反射仍然可以用来调用非动态生成的代码。例如,使用Reflection MethodInfo不会生成任何动态代码,它可以用来调用编译时定义的方法。因此,我认为仍然有可能打破早期绑定。我尝试了这个方法,但GetMethod似乎无法处理动态生成的代理。我得到了一个“system.marshalByRef上不存在方法”异常。而且这似乎是内存问题的原因。在我的例子中,我发现一些插件实际上正在加载到初始appdomain中。(但他们不应该服用1.5克,所以我还是不确定)