WPF CreateBitmapSourceFromHBitmap()内存泄漏

WPF CreateBitmapSourceFromHBitmap()内存泄漏

我需要逐个像素地绘制图像并将其显示在WPF中。我试图通过使用System.Drawing.Bitmap然后使用CreateBitmapSourceFromHBitmap()创建BitmapSource一个WPF图像控件来做到这一点。我在某处有内存泄漏,因为当CreateBitmapSourceFromBitmap()重复调用时,内存使用率会上升,并且在应用程序结束之前不会下降。如果我不打电话CreateBitmapSourceFromBitmap(),内存使用量没有明显变化。

for (int i = 0; i < 100; i++){
    var bmp = new System.Drawing.Bitmap(1000, 1000);
    var source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        bmp.GetHbitmap(), IntPtr.Zero, Int32Rect.Empty,
        System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
    source = null;
    bmp.Dispose();
    bmp = null;}

我该怎么做才能释放BitmapSource记忆?


12345678_0001
浏览 1271回答 3
3回答

翻阅古今

每当处理非托管句柄时,使用“安全句柄”包装器是个好主意:public&nbsp;class&nbsp;SafeHBitmapHandle&nbsp;:&nbsp;SafeHandleZeroOrMinusOneIsInvalid{ &nbsp;&nbsp;&nbsp;&nbsp;[SecurityCritical] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;SafeHBitmapHandle(IntPtr&nbsp;preexistingHandle,&nbsp;bool&nbsp;ownsHandle) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;base(ownsHandle) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetHandle(preexistingHandle); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;override&nbsp;bool&nbsp;ReleaseHandle() &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;GdiNative.DeleteObject(handle)&nbsp;>&nbsp;0; &nbsp;&nbsp;&nbsp;&nbsp;}}只要你展示一个句柄就构造一个(理想情况下你的API永远不会暴露IntPtr,它们总是返回安全句柄):IntPtr&nbsp;hbitmap&nbsp;=&nbsp;bitmap.GetHbitmap();var&nbsp;handle&nbsp;=&nbsp;new&nbsp;SafeHBitmapHandle(hbitmap&nbsp;,&nbsp;true);并像这样使用它:using&nbsp;(handle){ &nbsp;&nbsp;...&nbsp;Imaging.CreateBitmapSourceFromHBitmap(handle.DangerousGetHandle(),&nbsp;...)}SafeHandle基础为您提供自动一次性/终结器模式,您需要做的就是覆盖ReleaseHandle方法。

慕标琳琳

我有相同的要求和问题(内存泄漏)。我实施了标记为答案的相同解决方案。但是虽然解决方案有效,但它对性能造成了不可接受的打击。在i7上运行,我的测试应用程序看到了稳定的30-40%CPU,200-400MB RAM增加,垃圾收集器几乎每毫秒运行一次。由于我正在进行视频处理,因此我需要更好的性能。我想出了以下内容,以为我会分享。可重用的全局对象//set&nbsp;up&nbsp;your&nbsp;Bitmap&nbsp;and&nbsp;WritableBitmap&nbsp;as&nbsp;you&nbsp;see&nbsp;fitBitmap&nbsp;colorBitmap&nbsp;=&nbsp;new&nbsp;Bitmap(..);WriteableBitmap&nbsp;colorWB&nbsp;=&nbsp;new&nbsp;WriteableBitmap(..);//choose&nbsp;appropriate&nbsp;bytes&nbsp;as&nbsp;per&nbsp;your&nbsp;pixel&nbsp;format,&nbsp;I'll&nbsp;cheat&nbsp;here&nbsp;an&nbsp;just&nbsp;pick&nbsp;4int&nbsp;bytesPerPixel&nbsp;=&nbsp;4;//rectangles&nbsp;will&nbsp;be&nbsp;used&nbsp;to&nbsp;identify&nbsp;what&nbsp;bits&nbsp;changeRectangle&nbsp;colorBitmapRectangle&nbsp;=&nbsp;new&nbsp;Rectangle(0,&nbsp;0,&nbsp;colorBitmap.Width,&nbsp;colorBitmap.Height);Int32Rect&nbsp;colorBitmapInt32Rect&nbsp;=&nbsp;new&nbsp;Int32Rect(0,&nbsp;0,&nbsp;colorWB.PixelWidth,&nbsp;colorWB.PixelHeight);转换代码private&nbsp;void&nbsp;ConvertBitmapToWritableBitmap(){ &nbsp;&nbsp;&nbsp;&nbsp;BitmapData&nbsp;data&nbsp;=&nbsp;colorBitmap.LockBits(colorBitmapRectangle,&nbsp;ImageLockMode.WriteOnly,&nbsp;colorBitmap.PixelFormat); &nbsp;&nbsp;&nbsp;&nbsp;colorWB.WritePixels(colorBitmapInt32Rect,&nbsp;data.Scan0,&nbsp;data.Width&nbsp;*&nbsp;data.Height&nbsp;*&nbsp;bytesPerPixel,&nbsp;data.Stride); &nbsp;&nbsp;&nbsp;&nbsp;colorBitmap.UnlockBits(data);&nbsp;}实施例//do&nbsp;stuff&nbsp;to&nbsp;your&nbsp;bitmapConvertBitmapToWritableBitmap();Image.Source&nbsp;=&nbsp;colorWB;结果是稳定的10-13%CPU,70-150MB RAM,垃圾收集器在6分钟运行中仅运行两次。
打开App,查看更多内容
随时随地看视频慕课网APP