vb.net 托管内存和堆是稳定的,但进程内存使用导致崩溃
vb.net managed memory and heaps are stable but process memory usage causes crash
我有一个应用程序读取带有图像名称的 csv 文件,调用打开图像的子程序,扫描以找到形状中的黄色像素,并解析左上角,注释 csv 数据并写入记录。 Managed Heap 和 Native heap 内存是稳定的,但进程内存每个图像增长 350MB。现在我让我的分析师将 csv 文件分成 25 个图像集。但这对于 20 岁左右的分析师来说是有风险的。
我处理了图像,尝试了 GCCollect(),大型 heapCompaction - 似乎没有任何帮助。我几乎每本 post 都读过,但似乎没有响起。我已经包含了代码 - 并试图去除显示和垃圾但留下了一些扫描比较。
我是运行.net 4.6.1,Win 10/64,16GB内存
子Process_CSV_Detail()
. . .按顺序读取 csv 文件,设置文件名,为用户显示,然后为每个图像调用工作进程 - 访问每个新图像时似乎会发生内存泄漏
Call BackgroundProcess2()
End Sub
Public 子 BackgroundProcess2()
GreenTest = 245
RedTest = 245
BlueTest = 70
Try
loadedImage = Image.FromFile(InputImageName)
Catch ex As Exception
. . . .Never gets here but some code
Finally
End Try
HeightVal = loadedImage.Height
WidthVal = loadedImage.Width
Dim MasterImage As New Bitmap(WidthVal, HeightVal, FormatVal)
MasterImage = loadedImage
。 . .现在正在寻找那个讨厌的像素
For ycounter = 1 To HeightVal - 1 Step PixelStride
For xcounter = 1 To WidthVal - 1 Step PixelStride
Dim PixelColor As Color = MasterImage.GetPixel(xcounter, ycounter)
PixelIsYellow = False
If PixelColor.R > RedTest Then
If PixelColor.G > GreenTest Then
If PixelColor.B < BlueTest Then
PixelIsYellow = True
YellowPixelCount = YellowPixelCount + 1
MasterImage.SetPixel(xcounter, ycounter, Color.FromArgb(&HFFFFFF00))
xPixelIsYellow = True
yPixelIsYellow = True
End If
End If
End If
If PixelIsYellow = True Then
'Now find the upper left corner
LeftXLoc = xcounter
LeftYLoc = ycounter
'Move to left until no more yellow, then back 1 step to
'locate left pixel location
Try
For xtestcounter = LeftXLoc To 1 Step -1
Dim PixelColorx As Color = MasterImage.GetPixel(xtestcounter, LeftYLoc)
If PixelColorx.R < RedTest Then
xPixelIsYellow = False
Exit Try
End If
If QA_Mode = False Then
If PixelColorx.G < GreenTest Then
xPixelIsYellow = False
Exit Try
End If
End If
If QA_Mode = True Then
If PixelColorx.G < GreenTest Then
xPixelIsYellow = False
Exit Try
End If
End If
If PixelColorx.B > 70 Then
xPixelIsYellow = False
Exit Try
End If
Next
Catch ex As Exception
Finally
End Try
LeftXLoc = xtestcounter + 1
'Move up until no more yellow, then back 1 step to locate left pixel location
Try
For ytestcounter = LeftYLoc To 1 Step -1
Dim PixelColory As Color = MasterImage.GetPixel(LeftXLoc, ytestcounter)
If PixelColory.R < RedTest Then
yPixelIsYellow = False
Exit Try
End If
If PixelColory.G < GreenTest Then
yPixelIsYellow = False
Exit Try
End If
If PixelColory.B > BlueTest Then
xPixelIsYellow = False
Exit Try
End If
Next
Catch ex As Exception
MsgBox("Error in locating upper left pixel")
Finally
End Try
LeftYLoc = ytestcounter + 1
OutputLine = CurrentDataLine & "," & xcounter & "," & ycounter & "," & LeftXLoc & "," & LeftYLoc
PrintLine(TargetFileNumber, OutputLine)
End If
Next
Next
loadedImage.Dispose()
MasterImage.Dispose()
' - I have tried these but no effect
'GC.Collect()
'Runtime.GCSettings.LargeObjectHeapCompactionMode = Runtime.GCLargeObjectHeapCompactionMode.CompactOnce
'Finalize()
End Sub
我希望有人会拥有让进程内存稳定的灵丹妙药 - 我已经尝试过 ANTS 但并不满意。
这两行是(至少部分)问题:
Dim MasterImage As New Bitmap(WidthVal, HeightVal, FormatVal)
MasterImage = loadedImage
您创建一个具有指定尺寸和像素格式的新位图,然后您立即替换 MasterImage
变量对新位图的引用与您的 loadedImage
的引用。现在新位图没有任何引用,没有被释放,因此在您关闭进程之前一直存在于内存中。相反,MasterImage
现在指的是 与 loadedImage
.
完全相同的 位图
因此,当您的代码处理位图时,它实际上是在尝试处理两次相同的位图:
loadedImage.Dispose()
MasterImage.Dispose() 'This is the exact same bitmap as loadedImage, which is already disposed of.
GDI+ 中的图像数据是非托管内存,这就是托管内存图保持稳定的原因。非托管内存简单地说就是任何不受垃圾收集器 (GC) 管理的内存,这就是为什么调用它的任何方法都无济于事的原因。它必须由程序员手动释放(在本例中通过调用 Dispose()
)。
解决方案是根本不创建新位图,因为您从未真正使用过它。完全删除 MasterImage
变量并直接对 loadedImage
进行操作。
我有一个应用程序读取带有图像名称的 csv 文件,调用打开图像的子程序,扫描以找到形状中的黄色像素,并解析左上角,注释 csv 数据并写入记录。 Managed Heap 和 Native heap 内存是稳定的,但进程内存每个图像增长 350MB。现在我让我的分析师将 csv 文件分成 25 个图像集。但这对于 20 岁左右的分析师来说是有风险的。
我处理了图像,尝试了 GCCollect(),大型 heapCompaction - 似乎没有任何帮助。我几乎每本 post 都读过,但似乎没有响起。我已经包含了代码 - 并试图去除显示和垃圾但留下了一些扫描比较。
我是运行.net 4.6.1,Win 10/64,16GB内存
子Process_CSV_Detail() . . .按顺序读取 csv 文件,设置文件名,为用户显示,然后为每个图像调用工作进程 - 访问每个新图像时似乎会发生内存泄漏
Call BackgroundProcess2()
End Sub
Public 子 BackgroundProcess2()
GreenTest = 245
RedTest = 245
BlueTest = 70
Try
loadedImage = Image.FromFile(InputImageName)
Catch ex As Exception
. . . .Never gets here but some code
Finally
End Try
HeightVal = loadedImage.Height
WidthVal = loadedImage.Width
Dim MasterImage As New Bitmap(WidthVal, HeightVal, FormatVal)
MasterImage = loadedImage
。 . .现在正在寻找那个讨厌的像素
For ycounter = 1 To HeightVal - 1 Step PixelStride
For xcounter = 1 To WidthVal - 1 Step PixelStride
Dim PixelColor As Color = MasterImage.GetPixel(xcounter, ycounter)
PixelIsYellow = False
If PixelColor.R > RedTest Then
If PixelColor.G > GreenTest Then
If PixelColor.B < BlueTest Then
PixelIsYellow = True
YellowPixelCount = YellowPixelCount + 1
MasterImage.SetPixel(xcounter, ycounter, Color.FromArgb(&HFFFFFF00))
xPixelIsYellow = True
yPixelIsYellow = True
End If
End If
End If
If PixelIsYellow = True Then
'Now find the upper left corner
LeftXLoc = xcounter
LeftYLoc = ycounter
'Move to left until no more yellow, then back 1 step to
'locate left pixel location
Try
For xtestcounter = LeftXLoc To 1 Step -1
Dim PixelColorx As Color = MasterImage.GetPixel(xtestcounter, LeftYLoc)
If PixelColorx.R < RedTest Then
xPixelIsYellow = False
Exit Try
End If
If QA_Mode = False Then
If PixelColorx.G < GreenTest Then
xPixelIsYellow = False
Exit Try
End If
End If
If QA_Mode = True Then
If PixelColorx.G < GreenTest Then
xPixelIsYellow = False
Exit Try
End If
End If
If PixelColorx.B > 70 Then
xPixelIsYellow = False
Exit Try
End If
Next
Catch ex As Exception
Finally
End Try
LeftXLoc = xtestcounter + 1
'Move up until no more yellow, then back 1 step to locate left pixel location
Try
For ytestcounter = LeftYLoc To 1 Step -1
Dim PixelColory As Color = MasterImage.GetPixel(LeftXLoc, ytestcounter)
If PixelColory.R < RedTest Then
yPixelIsYellow = False
Exit Try
End If
If PixelColory.G < GreenTest Then
yPixelIsYellow = False
Exit Try
End If
If PixelColory.B > BlueTest Then
xPixelIsYellow = False
Exit Try
End If
Next
Catch ex As Exception
MsgBox("Error in locating upper left pixel")
Finally
End Try
LeftYLoc = ytestcounter + 1
OutputLine = CurrentDataLine & "," & xcounter & "," & ycounter & "," & LeftXLoc & "," & LeftYLoc
PrintLine(TargetFileNumber, OutputLine)
End If
Next
Next
loadedImage.Dispose()
MasterImage.Dispose()
' - I have tried these but no effect
'GC.Collect()
'Runtime.GCSettings.LargeObjectHeapCompactionMode = Runtime.GCLargeObjectHeapCompactionMode.CompactOnce
'Finalize()
End Sub
我希望有人会拥有让进程内存稳定的灵丹妙药 - 我已经尝试过 ANTS 但并不满意。
这两行是(至少部分)问题:
Dim MasterImage As New Bitmap(WidthVal, HeightVal, FormatVal)
MasterImage = loadedImage
您创建一个具有指定尺寸和像素格式的新位图,然后您立即替换 MasterImage
变量对新位图的引用与您的 loadedImage
的引用。现在新位图没有任何引用,没有被释放,因此在您关闭进程之前一直存在于内存中。相反,MasterImage
现在指的是 与 loadedImage
.
因此,当您的代码处理位图时,它实际上是在尝试处理两次相同的位图:
loadedImage.Dispose()
MasterImage.Dispose() 'This is the exact same bitmap as loadedImage, which is already disposed of.
GDI+ 中的图像数据是非托管内存,这就是托管内存图保持稳定的原因。非托管内存简单地说就是任何不受垃圾收集器 (GC) 管理的内存,这就是为什么调用它的任何方法都无济于事的原因。它必须由程序员手动释放(在本例中通过调用 Dispose()
)。
解决方案是根本不创建新位图,因为您从未真正使用过它。完全删除 MasterImage
变量并直接对 loadedImage
进行操作。