从程序集创建实例会引发内存泄漏 [英] Creating an instance from assembly throws a memory leak

查看:98
本文介绍了从程序集创建实例会引发内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个桌面应用程序,需要在其他AppDomain中使用反射加载一些dll,调用一个方法并卸载AppDomain.我已经正确开发了它,但是最近需要加载和卸载的程序集数量有所增加,现在,在加载3个dll之后,当我尝试加载第4个dll时,出现此异常:

I have a desktop application where i need to load some dll using reflection in a different AppDomain, call a method and unload the AppDomain. I have correctly developed it, however the number of assemblies i need to load and unload has been increased recently, and now, after loading 3 dll, when i try to load the 4th dll I get this exception:

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)

在网上搜索后,我什至不知道出了什么问题.如果我在Visual Studio上调试应用程序,则它可以正常运行.它仅出现在已发布的应用程序上.这是相关代码:

After searching on the net, i can't even figure what's the problem. If I debug the application on visual studio it works properly. It only appear on the published application. This is the relevant code:

'DLLManager:

'DLLManager:

For Each bean As BankIntegration.AppUtil.bankBean In aux
        Dim dllPath As String = Path.Combine(DLL_FILES_DIR, bean.DllName)
        Dim download As Boolean = False

        If File.Exists(dllPath) Then
            Dim info As BankInterfaces.beans.DLLInfo = ReflectionCaller.Call(dllPath, bean.DllNameSpace & ".Connector", BankInterfaces.Util.BANKINTERFACE_NAMES.getDLLInfo, Nothing)
            'Irrelevant code here'
            info = Nothing
            'Irrelevant code here'
        End If

            'Irrelevant code here'
        GC.Collect()
    Next

'ReflectionCaller

'ReflectionCaller

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

推荐答案

在网上搜索2天后,我已经能够解决该错误.这是针对我情况的任何人的解决方案.

After 2 days searching on the net i have been able to resolve the error. This is the solution for anyone on my situation.

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

  1. The classes you want to load by reflection have to implement the IDisposable interface.
  2. These classes have to override the Dispose method. In this method, simply force the garbage collector:

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

这篇关于从程序集创建实例会引发内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆