项目中有OCR识别数据功能,用的OpenCV3.4的库,实际使用中发现类库有内存泄漏问题,先想的方案是加载OpenCV类库的dll使用动态加载方式定时卸载重新加载,实际测试发现无效,后来用的方案是使用exe调用OpenCV库,使用进程间通讯传值给主程序,定时重启exe程序解决的.本文主要记录动态加载/卸载类库的内容.
1.在需要调用项目中新建类库CanUnLoadClass并继承自MarshalByRefObject,在类CanUnLoadClass中使用反射机制加载被调用方
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace WinFormsOCR
{
public class CanUnLoadClass : MarshalByRefObject
{
Assembly assemble = null;
IDisposable bb = null;
public void LoadAssembly(int millSecond, int x, int y, int width, int height, IntPtr mainWindowHandle)
{
assemble = Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory + "\\OCR340.dll");//被调用dll
bb = (IDisposable)assemble.CreateInstance(
"OCR340.HelperOcr340",//要实例化的类,完整名称[命名空间.类名]
true,
BindingFlags.Default,
null,
new object[] { millSecond, x, y, width, height, mainWindowHandle },//要实例化类的构造函数参数数组,和构造函数一一对应
null,
null);
}
public void Close()
{
if (bb != null) { bb.Dispose(); }
}
}
}
2.加载/卸载类库方法
AppDomain tmpAppDomain = null;
private void StartOCR340()
{
StopOCR340();
tmpAppDomain = AppDomain.CreateDomain("Ocr340Domain" + Environment.TickCount);//为应用程序域起个名字
CanUnLoadClass obj = (CanUnLoadClass)tmpAppDomain.CreateInstanceFromAndUnwrap(@"WinFormsOCR.exe", "WinFormsOCR.CanUnLoadClass");//第一个参数是CanUnLoadClass所在程序集名称,第二个参数是CanUnLoadClass完整名称[命名空间.类名]
obj.LoadAssembly(GlobalStatic.OCRMillSecond,
GlobalStatic.OCRX, GlobalStatic.OCRY, GlobalStatic.OCRWidth, GlobalStatic.OCRHeight,
GlobalStatic.MainWindowHandle);
Console.WriteLine("加载应用程序域:" + tmpAppDomain.FriendlyName);
}
private void StopOCR340()
{
try
{
if (tmpAppDomain != null)
{
string str = tmpAppDomain.FriendlyName;
AppDomain.Unload(tmpAppDomain);
tmpAppDomain = null;
GC.Collect();
Console.WriteLine("卸载应用程序域:" + str);
}
}
catch { }
}
3.正常程序运行时已加载的dll是无法删除的,验证是否卸载成功,只要看dll能否删除即可
4.完整源码链接 OCR识别动态加卸载dll
