ImageList / OutOfMemoryException Изображение

голоса
4

Я страдаю от OutOfMemoryException при получении изображения из ImageList я не смог найти подходящее решение проблемы.

У меня есть пользовательский элемент управления ListView, который прилагается к нему событие для рисования ListViewItems. Это затем вызывает статический метод, который предназначен для рисования элемента.

Для ListView около 300 пунктов, мы получаем память подпрыгивать вокруг 100Mb каждый раз, когда ListView прокручивается. Код обижая был выследили на следующее:

Image image = item.ImageList.Images[item.ImageKey];
if (image != null)
{
    Size imageOffset = new Size((bounds.Width - image.Width) / 2, 2); 
    Point imagePosition = bounds.Location + imageOffset;
    graphics.DrawImageUnscaled(image, imagePosition);
}

Кажется, (конечно, на WinXP), что сбор мусора не работает должным образом, что приводит к памяти по спирали. Мы попытались добавление image.Dispose () непосредственно после блока кода, чтобы исправить эту проблему, но это не имеет никакого эффекта.

Единственное решение, которое я смог найти до сих пор, в конце статического метода для вызова GC.Collect (). Проблема с этим, однако, что тогда заставляет ListView перекрасить себя медленно, и вы в конечном итоге получить артефакты на экране в то время как он пытается перерисовать.

Кто-нибудь еще сталкивался с этим? Или знает обходной путь?

Задан 19/05/2009 в 14:00
источник пользователем
На других языках...                            


2 ответов

голоса
4

Вы утилизация graphics? Кроме того , вы располагаете изображение , как вы сказали , то вам нужно будет убедиться , что он взят из ImageList или вызовет больше проблем. Что какой формат образа?

В общем, когда вы выходите из проблем с памятью, когда изображения участвуют, ваш вопрос будет либо какой-либо метод не нравится какой-то формат изображение, или 9/10 раз, вы поняли жизненный цикл одного из графических объектов.

  • Проверьте все ваше Graphicsиспользование и поместить их в usingблоках.
  • Проверьте Imageжизненный цикл и быть осторожным с копированием их, располагая их, закрывая потоки , лежащие в основе и т.д.
  • Загрузите менеджер памяти (VS2008 имеет один встроенный) и посмотреть, что не получает очищены хорошо.

РЕДАКТИРОВАТЬ:

Вот это лучший вариант , я могу найти, использовать ImageList.Draw(graphics, x, y, width, height, index). Это будет использовать внутреннюю ручку , вместо создания копии изображения.

Ответил 20/05/2009 в 05:42
источник пользователем

голоса
0

Мне удалось решить эту проблему в моем приложении.

Джейсон есть ответ, вы должны убедиться, что вы используете «с помощью» блоков, или их эквивалент.

Я использую VB, и эквивалент, чтобы использовать Try ... Catch ... Наконец, когда я создал новый точечный рисунок, вызывая BitMap.Dispose и не устанавливая Bitmap = ничего в «Наконец» части.

Это, кажется, действительно общая проблема, судя по часам я провел пытаясь Google этого. Приведенный ниже код позволяет также любое изображению, чтобы сохранить соотношение сторон, когда сводится к миниатюре, другой вопрос, который, кажется, трудно Google!

Код:

Private Function AspectedImage(ByVal ImagePath As String, ByVal SizeWanted As Integer) As Image

    Dim myBitmap, WhiteSpace As System.Drawing.Bitmap
    Dim myGraphics As Graphics
    Dim myDestination As Rectangle
    Dim MaxDimension As Integer
    Dim ReductionRatio As Double

    Try

        'create an instance of bitmap based on a file
        myBitmap = New System.Drawing.Bitmap(ImagePath)



        'create a new square blank bitmap the right size
        If myBitmap.Height >= myBitmap.Width Then MaxDimension = myBitmap.Height Else MaxDimension = myBitmap.Width
        ReductionRatio = SizeWanted / MaxDimension
        WhiteSpace = New System.Drawing.Bitmap(SizeWanted, SizeWanted)

        'get the drawing surface of the new blank bitmap
        myGraphics = Graphics.FromImage(WhiteSpace)

        'find out if the photo is landscape or portrait
        Dim WhiteGap As Double

        If myBitmap.Height > myBitmap.Width Then 'portrait
            WhiteGap = ((myBitmap.Width - myBitmap.Height) / 2) * -1
            myDestination = New Rectangle(x:=CInt(WhiteGap * ReductionRatio), y:=0, Width:=Int(myBitmap.Width * ReductionRatio), Height:=Int(myBitmap.Height * ReductionRatio))
        Else 'landscape
            WhiteGap = ((myBitmap.Width - myBitmap.Height) / 2)
            'create a destination rectangle
            myDestination = New Rectangle(x:=0, y:=CInt(WhiteGap * ReductionRatio), Width:=Int(myBitmap.Width * ReductionRatio), Height:=Int(myBitmap.Height * ReductionRatio))
        End If

        'draw the image on the white square
        myGraphics.DrawImage(image:=myBitmap, rect:=myDestination)
        AspectedImage = WhiteSpace

    Catch ex As Exception
        myBitmap = New System.Drawing.Bitmap("")
        AspectedImage = New System.Drawing.Bitmap(4, 4)
        ImageBufferExceeded = True
        MsgBox("Image Buffer exceeded, too many images in memory. If the one(s) you want can't be seen, please restart the application and navigate straight to your images")
    Finally
        myBitmap.Dispose()
        myBitmap = Nothing
        WhiteSpace = Nothing
    End Try

End Function
Ответил 11/06/2009 в 20:08
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more