我有一种使用C++ DLL用佳能相机进行通信的应用,在该C++ DLL方法从C#应用程序调用。我在应用程序中看到的是,当拍照时,记忆会增加,当然。关闭“图像捕捉窗口”后,应用程序仍会保留与所有图像一样的内存量。内存泄漏C++/C#应用
由于我的应用程序存在多层WPF UserControls,我认为“图像预览UserControl”无法收集垃圾,因为其他控件订阅了从此控件触发的事件。经过一番谷歌搜索之后,我决定对事件实施Weak Reference Pattern
。
//Source code found here: http://paulstovell.com/blog/weakevents
public sealed class WeakEventHandler<TEventArgs> where TEventArgs : EventArgs
{
private readonly WeakReference _targetReference;
private readonly MethodInfo _method;
public WeakEventHandler(EventHandler<TEventArgs> callback)
{
_method = callback.Method;
_targetReference = new WeakReference(callback.Target, true);
}
public void Handler(object sender, TEventArgs eventArgs)
{
var target = _targetReference.Target;
if (target != null)
{
var callback =
(Action<object, TEventArgs>)
Delegate.CreateDelegate(typeof (Action<object, TEventArgs>), target, _method, true);
if (callback != null)
{
callback(sender, eventArgs);
}
}
}
}
因此,如果我忘记取消订阅一些活动,GC将收集它们。一些经过测试,这种方法没有工作,所以我决定用Redgate ANTS Memory Profiler
我花了三年的快照:
- 拍摄图像
- 之前,我花了后4个图像
- 的破坏以后WPF的控制器比较快照1和3时
其结果是:
正如你可以看到分配的非托管内存的量是很大的问题在这里。我首先想到的是,当“图像捕捉窗口”关闭时,C++ DLL不会释放分配的内存。
我是正确的问题是在C++插件?我可以排除C#应用程序吗?据我所知,所有用.NET编写的代码都是托管内存。
基于这里的注释是图像从C++插件的C#插件如何到达:
从C++插件有这样的回调:
_resultcallback(img->GetImageInfo().Data, img->GetImageInfo().Width, img->GetImageInfo().Height, img->GetImageInfo().BPP);
而且方法其接收关于C#侧的图像:
private void OnResultImageCallback(IntPtr imagePtr, int width, int height, int bitsPerPixel)
{
_state = CameraState.InitializedStandby;
_cbResultData.Width = width;
_cbResultData.Height = height;
_cbResultData.BitsPerPixel = bitsPerPixel;
int memSize = bitsPerPixel * width * height/8;
_cbResultData.data = new byte[memSize];
Marshal.Copy(imagePtr, _cbResultData.data, 0, memSize);
_deleteAllocatedImageFunction(imagePtr);
if (ImageCaptured != null)
ImageCaptured(_cbResultData.data, _cbResultData.Width, _cbResultData.Height, _cbResultData.BitsPerPixel);
_cbResultData.data = null;
}
我也有以清除在我的C++,其TA所分配的存储器的方法KES在字节指针这样的:
BOOL CanonEDSDKWnd::ClearImageBuffer(BYTE* img) {
_debug->Write(_T("CanonEDSDKWnd::ClearImageBuffer"));
delete[] img;
return TRUE;
}
,其从与所述IntPtr
从回调
_deleteAllocatedImageFunction(imagePtr)C#代码调用;
如何图像到达从C C#代码++图书馆?如何调用非托管方法?如何将图像存储在托管端?没有关于代码的知识,很难说任何有用的东西。 – 2014-10-28 08:31:14
请参阅我的编辑。我认为它应该是必不可少的部分。 – 2014-10-28 08:38:06
我很确定回调中的'img'指向的对象必须以某种方式被释放。你应该有一个C++函数来删除img,并且在将数据复制到托管存储之后应该调用它。 – 2014-10-28 08:47:05