Управляемая память и куча vb.net стабильны, но использование памяти процесса вызывает сбой - PullRequest
0 голосов
/ 01 апреля 2019

У меня есть приложение, которое читает CSV-файл с именем изображения, вызывает подпрограмму, которая открывает изображение, сканирует, чтобы найти желтый пиксель в форме, и разрешает левый верхний угол, комментирует данные CSV и записывает запись.,Управляемая куча и собственная куча памяти стабильны, но объем памяти процесса увеличивается на 350 МБ на изображение.На данный момент мои аналитики разбивают CSV-файл на 25 наборов изображений.Но это рискованно с 20-ти процентными аналитиками.

Я располагаю изображения, пробовал GCCollect (), большой heapCompaction - кажется, ничего не помогает.Я прочитал почти каждый пост, и, кажется, ничего не звонит.Я включил код - и попытался удалить дисплеи и мусор, но оставил некоторые сравнения сканирования.

Я использую .net 4.6.1, Win 10/64, 16 ГБ памяти

Sub Process_CSV_Detail ().,,последовательно читать CSV-файл, задавать имена файлов, отображать для пользователя, а затем вызывать рабочий процесс для каждого изображения - утечка памяти, по-видимому, происходит при доступе к каждому новому изображению

    Call BackgroundProcess2()

End Sub

Public 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 Ответ

1 голос
/ 01 апреля 2019

Эти две строки (по крайней мере, часть) проблемы:

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 напрямую.

...