.net 从程序集创建实例会引发内存泄漏

.net 从程序集创建实例会引发内存泄漏,.net,reflection,memory-leaks,.net,Reflection,Memory Leaks,我有一个桌面应用程序,需要在不同的AppDomain中使用反射加载一些dll,调用一个方法并卸载AppDomain。我已经正确地开发了它,但是最近我需要加载和卸载的程序集的数量增加了,现在,在加载3个dll后,当我尝试加载第4个dll时,我得到了以下异常: System.TypeInitializationException: An exception occurred on startup type '<Module>'. ---> System.AccessViolatio

我有一个桌面应用程序,需要在不同的AppDomain中使用反射加载一些dll,调用一个方法并卸载AppDomain。我已经正确地开发了它,但是最近我需要加载和卸载的程序集的数量增加了,现在,在加载3个dll后,当我尝试加载第4个dll时,我得到了以下异常:

System.TypeInitializationException: An exception occurred on startup type '<Module>'. ---> System.AccessViolationException: Attempted to read or write protected memory. This often indicates that other memory is corrupt.

en .cctor()

--- End of monitoring the inner exception stack ---

en System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)

en System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

en System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark)

en System.Activator.CreateInstance(Type type, Boolean nonPublic)

en System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, StackCrawlMark& stackMark)

en System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)

en System.Reflection.Assembly.CreateInstance(String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)

en BankIntegration.ReflectionCaller.CallInternal(String dll, String typename, String method, Object[] parameters)

en BankIntegration.ReflectionCaller.CallInternal(String dll, String typename, String method, Object[] parameters)

en BankIntegration.ReflectionCaller.Call(String pathToDLL, String typename, String method, Object[] parameters)

en BankIntegration.DllManager.init_bank_conectors(Server service)

en BankIntegration.frmClient..ctor(Server service, String dllPath, Int64 idclient)

en AVISync.frmInit.Button_clicked(Object sender, ItemClickEventArgs e)
“反射调谐器

Public Shared Function [Call](ByVal pathToDLL As String, ByVal typename As String, ByVal method As String, ByVal ParamArray parameters As Object()) As Object
    Dim permissions As New Security.PermissionSet(Security.Permissions.PermissionState.Unrestricted)
    Dim adSetup As New AppDomainSetup()
    adSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory
    Dim dom As AppDomain = AppDomain.CreateDomain(Guid.NewGuid.ToString, AppDomain.CurrentDomain.Evidence, adSetup, permissions)
    Dim ld As ReflectionCaller = DirectCast(dom.CreateInstanceAndUnwrap(Reflection.Assembly.GetExecutingAssembly().FullName, GetType(ReflectionCaller).FullName), ReflectionCaller)
    Dim result As Object = ld.CallInternal(pathToDLL, typename, method, parameters)

    AppDomain.Unload(dom)
    dom = Nothing
    ld = Nothing
    GC.Collect()
    Return result
End Function

Private Function CallInternal(dll As String, typename As String, method As String, parameters As Object()) As Object
    Dim a As Reflection.Assembly = Reflection.Assembly.LoadFile(dll)
    Dim o As Object = a.CreateInstance(typename) '<-- This line throws the exception after a few iterations'
    Dim t As Type = o.[GetType]()
    Dim m As Reflection.MethodInfo = t.GetMethod(method)
    Dim result As Object = m.Invoke(o, parameters)

    a = Nothing
    o = Nothing
    t = Nothing
    m = Nothing
    GC.Collect()
    Return result
End Function
Public Shared Function[Call](ByVal pathToDLL作为字符串,ByVal typename作为字符串,ByVal method作为字符串,ByVal paramary parameters作为Object())作为对象
将权限设置为新的Security.PermissionSet(Security.permissions.PermissionState.Unrestricted)
Dim AD设置为新的AppDomainSetup()
adSetup.ApplicationBase=AppDomain.CurrentDomain.BaseDirectory
Dim dom作为AppDomain=AppDomain.CreateDomain(Guid.NewGuid.ToString、AppDomain.CurrentDomain.Evidence、adSetup、权限)
Dim ld As ReflectionCaller=DirectCast(dom.CreateInstanceAndUnwrap(Reflection.Assembly.GetExecutionGassembly().FullName,GetType(ReflectionCaller.FullName),ReflectionCaller)
将结果调整为Object=ld.CallInternal(路径、类型、方法、参数)
AppDomain.Unload(dom)
dom=Nothing
ld=无
GC.Collect()
返回结果
端函数
私有函数CallInternal(dll作为字符串,typename作为字符串,方法作为字符串,参数作为Object())作为对象
将a设置为Reflection.Assembly=Reflection.Assembly.LoadFile(dll)

Dim o As Object=a.CreateInstance(typename)“在网上搜索2天后,我已经能够解决错误。这是我处境中任何人的解决方案

  • 要通过反射加载的类必须实现IDisposable接口
  • 这些类必须重写Dispose方法。在此方法中,只需强制垃圾收集器:

    GC.Collect(3)
    GC.SuppressFinalize(Me)
    

  • 这与内存泄漏无关。这是一个非托管崩溃。@usr首先,我认为这一定是dll的问题。然而,当我改变加载顺序时,它也有同样的问题。它总是在第四个dll上崩溃。此外,异常显示:“试图读取或写入受保护内存”。我想这一定是卸载的问题,卸载会继续阻塞内存这正是我要寻找的,但是您是通过using(){}子句调用被重写的dispose,还是在完成时手动调用的?在我的例子中,我手动调用了它们,但是我认为使用
    通过
    处理它的效果完全相同。但是如果不强制转换到明确定义dispose的对象或接口,您如何在对象=a.CreateInstance(typename)
    时对Dim o创建的对象调用dispose(),我没有手动调用dispose:)我在将近一年前问过这个问题,我无法查看使用该代码的项目。我记不起我在发行版上使用的确切代码了。
    GC.Collect(3)
    GC.SuppressFinalize(Me)