Image.RotateFlip泄漏内存:/

sir*_*est 6 .net c# drawing memory-leaks bitmap

虽然我已经编程了大约11年(主要是VB6,过去6个月C#),但它是第一次真正提出问题:)我已经找到了我的所有答案来自teh interwebz但是这个问题我无法解决自己.您的网站是最有帮助的地方之一,我得到了最好的答案!

我将展示我正在使用的代码(相关内容的摘录).问题是当使用RotateFlip方法时,内存会迅速增加到~200M,然后在一段时间后由GC收集.调用它的主要方法每秒迭代大约30次,因此这里的性能至关重要.我尝试使用图形矩阵变换,但这有时会失败并显示非翻转图像.应用程序本身基于使用网络摄像头,隐藏预览,获取回调图片并在图片框中显示.然后它覆盖了另一个类上的矩形.这是使用回调而不是预览窗口的原因.

Capture.cs类:

internal Bitmap LiveImage;

    int ISampleGrabberCB.BufferCB(double bufferSize, IntPtr pBuffer, int bufferLen)
    {
        LiveImage = new Bitmap(_width, _height, _stride, PixelFormat.Format24bppRgb, pBuffer);

        if (ExpImg) // local bool, used rarely when the picture saving is triggered
        {
            LiveImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
            var a = LiveImage.Clone(new Rectangle(Currect.Left, Currect.Top, Currect.Width, Currect.Height),
                                    LiveImage.PixelFormat);
            using (a)
                a.Save("ocr.bmp", ImageFormat.Bmp);

        }
        else // dmnit, rotateflip leaks like h*ll but matrix transform doesn't sometimes flip :S
        {
            LiveImage.RotateFlip(RotateFlipType.RotateNoneFlipY);
            /*using (var g = Graphics.FromImage(LiveImage))
            {
                g.Transform = _mtx;
                g.DrawImage(LiveImage, 0, 0);
            }*/
        }
        GC.Collect(); // gotta use it with rotateflip, otherwise it gets crazy big, like ~200M :O
        return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

在主要形式我有一个事件,正在更新图片框中的图片:

private void SetPic()
{
    pctCamera.Image = _cam.LiveImage;
    _cam.PicIsFree = false;
}
Run Code Online (Sandbox Code Playgroud)

因为我需要将图像转换为另一个类中的主窗体,然后我认为最合乎逻辑的是在每个回调帧上更新的暴露位图.我不想使用矩阵变换的原因是因为它速度较慢,有时使用这种速度无法翻转图像,这种行为的频率因不同的PC具有不同的硬件功能和CPU速度而异,也是最快的帧率带有1.2GHz CPU的30fps非常频繁地显示出来.

那么,你能帮我解决一下吗?我实际上并没有在当前版本中使用它,我正在使用注释掉的矩阵变换,因为我觉得使用GC.Collect很糟糕:(

谢谢!!!

Han*_*ant 5

pctCamera.Image = _cam.LiveImage;
Run Code Online (Sandbox Code Playgroud)

像你观察到的大量内存使用是一个肯定的迹象,你错过了在某处调用Dispose()的机会,让位图使用的非托管资源(主要是内存)尽早释放,而不是让垃圾收集器这样做.引用的语句就是这样一种情况,你没有处理图片框引用的旧图像.固定:

if (pctCamera.Image != null) pctCamera.Image.Dispose();
pctCamera.Image = _cam.LiveImage;
Run Code Online (Sandbox Code Playgroud)