vb.net托管的内存和堆是稳定的,但进程内存的使用会导致崩溃

时间:2019-04-01 16:31:45

标签: vb.net memory-leaks gdi+

我有一个应用程序,该应用程序读取带有图像名称的csv文件,调用一个打开图像的子程序,扫描以找到形状中的黄色像素,然后解析左上角,为csv数据添加注释并写入记录。托管堆和本机堆内存稳定,但是进程内存每个映像增长350MB。现在,我让我的分析师将csv文件切成25个图像集。但这对于20岁左右的分析师来说是有风险的。

我处理了图像,尝试了GCCollect(),使用了大的heapCompaction-似乎无济于事。我阅读了每个帖子的大部分内容,似乎没有响。我已经包含了代码-并试图去除显示和垃圾,但留下了一些扫描比较。

我正在运行.net 4.6.1,Win 10 / 64、16GB内存

子Process_CSV_Detail()         。 。 。依次读取csv文件,设置文件名,为用户显示,而不是为每个图像调用工作过程-似乎在访问每个新图像时发生内存泄漏

    Call BackgroundProcess2()

End Sub

公共子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,但没有任何乐趣。

1 个答案:

答案 0 :(得分:1)

这两行是(至少是部分)问题:

Dim MasterImage As New Bitmap(WidthVal, HeightVal, FormatVal)

MasterImage = loadedImage

您创建具有指定尺寸和像素格式的 new 位图,然后立即 替换 MasterImage变量对与您的loadedImage的新位图。现在,新的位图没有任何引用,也没有被处置,因此将保留在内存中,直到您关闭进程。相反,MasterImage现在与<{1}所指的是完全相同的位图。

因此,当您的代码处理位图时,实际上是在尝试两次处理相同位图:

loadedImage

GDI +中的图像数据是未损坏的内存,这就是托管内存图保持稳定的原因。非托管内存只是说任何不受垃圾收集器(GC)管理的内存,这就是为什么调用其任何方法都无济于事的原因。它必须由程序员手动释放(在这种情况下,通过调用loadedImage.Dispose() MasterImage.Dispose() 'This is the exact same bitmap as loadedImage, which is already disposed of. )。

解决方案是根本不创建该新位图,因为您从未真正使用过它。完全删除Dispose()变量,然后直接在MasterImage上进行操作。