WPF二维码扫描器内存溢出错误求助(基于AForge.Video.DirectShow)
解决WPF二维码扫描内存溢出问题
核心问题:未释放GDI位图句柄
你的内存溢出根源在BitmapToImageSource方法中:调用bitmap.GetHbitmap()会在非托管内存中创建GDI位图对象,但.NET垃圾回收器不会自动回收这类非托管资源。每帧都创建新的GDI对象却不释放,短时间内就会导致内存爆炸。
修复代码
修改BitmapToImageSource方法,添加非托管资源释放逻辑,需要引入System.Runtime.InteropServices命名空间:
using System.Runtime.InteropServices; private ImageSource BitmapToImageSource(Bitmap bitmap) { IntPtr hBitmap = bitmap.GetHbitmap(); ImageSource imageSource = null; try { imageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); } finally { // 强制释放非托管GDI句柄 DeleteObject(hBitmap); } return imageSource; } // 导入Windows API用于释放GDI对象 [DllImport("gdi32.dll")] private static extern bool DeleteObject(IntPtr hObject);
额外优化建议
复用BarcodeReader实例
不要在NewFrame事件中每次都创建BarcodeReader,改为类级别的字段,减少对象初始化开销:private BarcodeReader _barcodeReader; public Scanner() { InitializeComponent(); _barcodeReader = new BarcodeReader(); InitializeCamera(); }后续在
NewFrame中直接使用_barcodeReader.Decode(bitmap)即可。避免阻塞视频线程
用Dispatcher.BeginInvoke替代Invoke,防止UI线程阻塞导致视频帧堆积:Application.Current.Dispatcher.BeginInvoke(() => { cameraImage.Source = BitmapToImageSource(bitmap); });扫描完成后的资源清理
扫描到二维码后,确保视频源完全停止再清理对象,避免残留资源:videoSource.NewFrame -= VideoSource_NewFrame; videoSource.SignalToStop(); videoSource.WaitForStop(); // 等待视频源完全停止 Application.Current.Dispatcher.Invoke(() => { cameraImage.Source = null; videoSource = null; videoDevices = null; myframe.frame.Content = new Scanned(bitmap, path, false, false); });
为什么之前的尝试无效
你之前在扫描完成后释放bitmap或置空对象,只能回收托管资源,但内存泄漏的核心是非托管GDI句柄,这些资源必须手动调用DeleteObject才能释放,GC无法自动处理。
内容的提问来源于stack exchange,提问作者Rushaan
相关产品推荐
相关产品推荐

