Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.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中,但也加载到AppDomain.CurrentDomain中,从而导致内存泄漏_C#_Reflection_Console Application_Appdomain - Fatal编程技术网

C# 将程序集加载到AppDomain中,但也加载到AppDomain.CurrentDomain中,从而导致内存泄漏

C# 将程序集加载到AppDomain中,但也加载到AppDomain.CurrentDomain中,从而导致内存泄漏,c#,reflection,console-application,appdomain,C#,Reflection,Console Application,Appdomain,我必须执行从jscript到另一个appdomain而不是当前appdomain的某行。为此,我有以下代码 AppDomain ad = null; try { ad = AppDomain.CreateDomain("new AD" + new Random(), null, null); ad.CreateInstanceAndUnwrap ( assembly, type, t

我必须执行从jscript到另一个appdomain而不是当前appdomain的某行。为此,我有以下代码

AppDomain ad = null;
try
{
    ad = AppDomain.CreateDomain("new AD" + new Random(), null, null);

    ad.CreateInstanceAndUnwrap
            (
            assembly,
            type,
            true,
            BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance,
            null,
            args,
            null,
            null,
            null
            );

}
catch (Exception e)
{
    throw new Exception("Automated script engine had an error. " + e.Message + "\n" + e.InnerException.StackTrace + "\n" + e.HelpLink);
}
finally
{
    if (ad != null)
    {
            Assembly[] a = ad.GetAssemblies();
            Console.WriteLine(a.Length);
            Assembly[] mainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
            Console.WriteLine(mainAssemblies.Length);
            AppDomain.Unload(ad);
            GC.AddMemoryPressure(GC.GetTotalMemory(true));
            GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
            GC.Collect();
            ad = null;
        }
    }
}
但是,当我检查加载到当前AppDomain中的所有程序集时(通过
AppDomain.CurrentDomain.GetAssemblys()
),我的asembly也会加载

由于我可能必须运行
2000测试
,我知道
2000程序集
将加载到我的
CurrentDomain

是否有方法将此程序集加载到AppDomain,但不将其添加到CurrentDomain


finally
块中的方法调用只是我在这里的尝试。如果它们没有用处,请不要对我进行评判。

IIRC在.NET 2.0中无法卸载程序集,但如果在以后的版本中可能,请纠正我,我没有检查过。所以,确保这是可能的,因为从前卸货是不可能的

第二,需要2000个不同的文件才能有2000个不同的程序集。也许你的意思是加载相同的组件2000次?在这种情况下,内存中实际上只有一个程序集

有一种方法可以只将反射数据加载到内存中,而不实际加载程序集,但这不是您想要的


GC在这里帮不了什么忙。查看测试驱动开发以获取更多的指针…

首先,您必须了解,当程序集加载到appdomain中时,您无法卸载任何程序集

要确保程序集未加载到您的
main
app域中,您需要远程处理。 这意味着您的
类型
必须派生自
MarshalByRefObject
,并且必须是
可序列化的


GC
不负责卸载或加载任何程序集。垃圾收集器确保对托管内存进行memory清理。

泄漏的罪魁祸首是:

Assembly[] a = ad.GetAssemblies();
在不加载程序集的情况下,无法将程序集从一个AppDomain传递到另一个AppDomain。因此,尽管您最初已将程序集加载到“ad”中,但调用
AppDomain.GetAssemblies
会将它们加载到当前AppDomain(而不是“ad”变量)

克服此问题的最简单方法是向MarshalByRefObject派生类(示例中的
type
变量)添加一个方法,该方法返回
AssemblyName
对象,而这些对象不会导致对主AppDomain的泄漏

public AssemblyName[] GetAssemblyNames()
{
    return AppDomain.CurrentDomain
                    .GetAssemblies()
                    .Select(asm => asm.GetName()).ToArray();
}
而不是:

Assembly[] a = ad.GetAssemblies();
你可以:

AssemblyNames[] a = someRemoteObject.GetAssemblyNames();
其中,
someRemoteObject
是调用
CreateInstanceAndUnwrap
的返回值