4

我有一个内存泄漏问题。

我有这个代码button_click

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

    Dim ms As New IO.MemoryStream
    Dim bm As New Bitmap("\Application Data\imgs\IMG22.jpg")
    bm.Save(ms, Drawing.Imaging.ImageFormat.Jpeg)
End Sub

当我在笔记本电脑上运行 .exe(我的意思是在具有完整 .net 框架的 windows7/32bits 下)时,此代码工作得很好,但是当我在具有 WindowsMo​​bile 6.1 的设备上运行应用程序时,应用程序会抛出此异常:

SmartDeviceProject22.exe
OutOfMemoryException

Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
at
System.Drawing.Image.Save(Stream stream, ImageFormat format)
at
SmartDeviceProject22.Form1.Button3_Click(Object sender, EventArgs e)
at
....

图像大小约为 200kb,宽度和高度约为 1500px。图片详情:

  • 尺寸:1536x2048
  • 水平分辨率:72dpi
  • 水平分辨率:72dpi
  • 位深:24
  • 分辨率单位:2
  • 颜色表示:sRGB -

任何帮助将不胜感激。

我尝试了@asawyer 的代码,甚至删除了所有代码、参考等,但问题仍然存在,我猜这与图像的宽度/高度或紧凑框架有关。

还有什么建议吗?

问题的解决方案和解释 好吧,在测试了真正的问题之后,它不是内存泄漏,正如@pdriegen 所说的内存可用问题。

我将代码更改为此(并在移动设备上进行了测试):

 Dim fs As IO.FileStream = IO.File.OpenRead("\Application Data\ryder\IMG23.jpg")
 Dim arrb(fs.Length) As Byte     
 fs.Read(arrb, 0, arrb.Length)
 fs.Close()
 fs.Dispose()

通过上面的代码(显然),我得到了一个图像的字节()(数组),使用 dataSet 存储在数据库中。

总之:将位图对象加载到 memoryStream,这是个坏主意。非常感谢所有花时间阅读我的问题的人,特别是那些发布答案的人。

解决方案(如果需要在图片框中显示图片):

几周后,这可能是最好的(免费)解决方案:实现 ImageHelper,如下所述:ImageHelper

ImageHelper 的更新链接 https://opennetcf.com/2010/10/13/loading-parts-of-large-images-in-the-compact-framework/

此类/示例使用来自 OpenNetCF ( http://www.opennetcf.com/ )的绘图命名空间

它工作得很好,它解决了我将大位图加载到内存的内存问题,实际上我们加载了一个缩略图,因此内存大小大大减少并避免了 OutOfMemory 异常问题。

关于 Chris Tacke 我刚刚意识到关于 ImageHelper 和 OpenNetCF 的联合创始人的帖子的作者在 stackoverflow 上,这是他的个人资料:https ://stackoverflow.com/users/13154/ctacke

更新链接 https://opennetcf.com/2010/10/13/loading-parts-of-large-images-in-the-compact-framework/

4

2 回答 2

5

我不相信问题是内存泄漏。相反,问题是可用内存不足。

即使压缩后的图像大小为 200kb,当您将其作为位图加载时,它也会被解压缩并以原生位图格式存储在内存中。给定高度和宽度各 1500 像素,并假设位图格式为 32bpp(未指定时的默认值),您将看到 9MB 的分配内存

1500 * 1500 * 4 = 9MB。

鉴于移动设备操作系统中存在的内存限制(32MB/进程 - 由系统 dll 分配的空间),您很可能处于内存紧缩情况。我当然不知道运行此代码的应用程序分配了哪些其他内存。

在具有较小图像的同一设备上尝试相同的代码。你应该看到它执行得很好。

于 2012-06-14T15:44:33.137 回答
1

您泄漏的 Gdi 句柄,将流和位图包装在Using子句中。

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

    using ms As New IO.MemoryStream
        using bm As New Bitmap("\Application Data\imgs\IMG22.jpg")
            bm.Save(ms, Drawing.Imaging.ImageFormat.Jpeg)
        end using
    end using

End Sub
于 2012-06-14T13:32:04.927 回答