【问题标题】:C# Bitmap dispose memory usageC#位图处理内存使用情况
【发布时间】:2017-05-08 16:49:31
【问题描述】:

我目前正在将网络摄像头功能实现到我正在创建的应用程序中,但是我遇到了一些内存使用问题。

我的功能如下图

这是第一个实现

private void webcam_newFrame(object sender, NewFrameEventArgs eventArgs) {
    if (!_pause) {
        var img = (Bitmap) eventArgs.Frame.Clone();
        pbPicture.BackgroundImage = img;            
    }
}

但是,这段代码导致了巨大的内存泄漏,运行了 2gb(我假设是 ram)。由于内存不足而崩溃之前。 然后我更改了代码以处理位图,就像这样

private void webcam_newFrame(object sender, NewFrameEventArgs eventArgs) {
    if (!_pause) {
        var img = (Bitmap) eventArgs.Frame.Clone();
        pbPicture.BackgroundImage = img;
        img.Dispose(); // This causes exception
    }
}

这会导致在 System.Drawing.dll 中引发异常:“System.ArgumentException”。

附加信息:参数无效。

在以下调用此表单的代码上:

WebcamForm wForm = new WebcamForm();
wForm.ShowDialog();

于是我把函数改成了这样:

private void webcam_newFrame(object sender, NewFrameEventArgs eventArgs) {
    if (!_pause) {
        pbPicture.BackgroundImage = (Bitmap)eventArgs.Frame.Clone();
        GC.Collect();
    }
}

此代码正常运行,内存使用量保持在 360mb 左右,这是一致的,考虑到应用程序,这是一个合理的数字。

我的问题是,在每一帧上强制进行垃圾收集是一个很好的解决方案吗?有没有潜在的问题?

我确信过去我已经看到强制垃圾收集是一件坏事的答案,但是我想不出任何替代方法来解决这个问题。

干杯

【问题讨论】:

    标签: c# memory bitmap garbage-collection


    【解决方案1】:

    经常调用垃圾收集器是一种不好的做法。

    尝试在新位图之后处理旧位图。

    private void webcam_newFrame(object sender, NewFrameEventArgs eventArgs) {
      if (!_pause) {
          Bitmap oldBitmap = (Bitmap)pbPicture.BackgroundImage;
          pbPicture.BackgroundImage = (Bitmap)eventArgs.Frame.Clone();
          oldBitmap.Dispose();
      }
    }
    

    【讨论】:

    • 请注意,如果没有默认背景图像,您的代码将在第一次调用时抛出空引用异常。
    【解决方案2】:

    您需要处理 BackgroundImage 的旧值,而不是您传入的新值。

    private void webcam_newFrame(object sender, NewFrameEventArgs eventArgs) {
        if (!_pause) {
            var img = (Bitmap) eventArgs.Frame.Clone();
            var oldImg =  pbPicture.BackgroundImage;
            pbPicture.BackgroundImage = img;
            oldImg?.Dispose();
        }
    }
    

    【讨论】:

    • 为此欢呼,但它会恢复为在 System.Drawing.dll 中引发 System.ArgumentException 错误,如我原来的问题中所述。我相信这是由处理位图引起的,因为在使用 GC.Collect() 的实现时我没有收到该错误。我无法让 Visual Studio 正常调试以进行调试,所以我不知道如何进一步缩小范围
    • 好吧忽略这一点,使用 PictureBox.Image 而不是 PictureBox.BackgroundImage 解决了这个问题。不知道为什么它会有所作为,但它是一个解决方案
    猜你喜欢
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 2016-07-07
    相关资源
    最近更新 更多