【问题标题】:Dealing with a memory leak when cropping images in vb.net在 vb.net 中裁剪图像时处理内存泄漏
【发布时间】:2018-06-29 02:05:16
【问题描述】:

当我将图像分解为子图像时,我不断收到系统内存不足错误。没有什么太花哨的事情,只是将图像分成一堆较小的图像。这是我的代码:

Dim counterrr As Integer = 0
Dim sorucedir As String
Dim tardir As String
sorucedir = "C:\somedir\"
tardir = "C:\otherdir\"
Dim di2 As New DirectoryInfo(sorucedir)
Dim fiArr2 As FileInfo() = di2.GetFiles()
Dim fri2 As FileInfo
Dim hh As Integer
Dim ww As Integer
hh = 995 'height of source images
ww = 1080 'width of source images
Dim sizestepX As Integer = 180
Dim stepsizeY As Integer = 239
For i = 0 To ww - 1 Step sizestepX
    For j = 0 To hh - 1 Step stepsizeY
        For Each fri2 In fiArr2
            Dim BM2 As Bitmap
            BM2 = Image.FromFile(fri2.FullName)
            ''Threading.Thread.Sleep(3000)
            'bm2 = Image.FromFile(fri2.FullName)
            Dim BM3 As Bitmap
            Dim rect As New Rectangle(i, j, sizestepX, stepsizeY)
            BM3 = BM2.Clone(rect, Imaging.PixelFormat.DontCare)
            counterrr += 1
            Dim ss As String
            ss = tardir & counterrr & ".png"
            BM3.Save(ss, Imaging.ImageFormat.Png)
            BM3 = Nothing
        Next
    Next
Next

创建少至 6 个图像后出现错误(创建第 7 个图像时发生)。抛出错误的行是这样的:

BM3 = BM2.Clone(rect, Imaging.PixelFormat.DontCare)

如何修改我的代码,使它们的对象被正确处理(?),这样它们就不会泄漏内存。

【问题讨论】:

  • 使用Using 语句...如果该类型实现了 IDisposable 接口,则将该对象包装起来以便正确处理。
  • @Codexer 我试过同时使用 BM2 和 BM3,我仍然得到同样的错误。
  • 另外,您的循环中有一个FileInfo 数组,您需要提取每个对象,不要创建变量来引用循环中的对象。删除 fri2... 还有其他建议,但这不是代码审查。你的问题已经回答了,该怎么做......
  • 另外,如果您尝试了Using 声明,您不认为您应该将其添加到您的帖子中,这很重要,因为有些人只是在您已经尝试过时浪费了时间来帮助您这个。另外,如果你这样做了,为什么上面的代码没有显示这个?

标签: vb.net image


【解决方案1】:

Bitmap 类以及许多其他 GDI+ 类都实现了IDisposable,因为它们持有需要释放的底层 GDI 对象句柄。每个进程由操作系统限制为最大 GDI 对象数,通常为 10,000。您可以在 Windows 任务管理器中查看每个进程的活动 GDI 对象总数。要解决您的问题,您需要在您创建的每个Bitamp 对象超出范围之前手动调用Dispose 方法,或者您需要将每个Bitmap 变量声明包装在Using 块中(所以它会为你调用Dispose)。例如:

Using BM2 As Bitmap = Image.FromFile(fri2.FullName)
    Dim rect As New Rectangle(i, j, sizestepX, stepsizeY)
    Using BM3 As Bitmap = BM2.Clone(rect, Imaging.PixelFormat.DontCare)
        counterrr += 1
        Dim ss As String
        ss = tardir & counterrr & ".png"
        BM3.Save(ss, Imaging.ImageFormat.Png)
    End Using
End Using

注意:在最后将 BM3 变量设置为 Nothing 是没有意义的,就像你正在做的那样。这与任何事情无关。

【讨论】:

  • 嗨史蒂文,感谢您的意见 - 但是我仍然遇到问题!使用您的代码的复制粘贴,我仍然在图像编号 7 处遇到系统内存不足错误!
  • 如果你没有解决它,那么要么你的问题在你没有显示的代码中的其他地方,要么问题是它们是非常大的图像并且你的可寻址内存用完了(其中强制垃圾收集可能会有所帮助)。无论哪种方式,我们都无能为力,因为您发布的代码实际上并不是问题所在。图片有多大?堆栈跟踪是什么?您用完了哪种内存/资源?这是 32 位还是 64 位应用程序?您是否尝试过拍摄堆快照来比较对象数量?
  • @Codexer,是的,他做到了,但直到我发布我的答案之前,我什至没有看到它。其次,它仍然是一个问题,即使它不是 问题 :)
猜你喜欢
  • 2016-04-12
  • 1970-01-01
  • 1970-01-01
  • 2022-08-23
  • 1970-01-01
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多