我从痛苦的一个OutOfMemoryException当获得的图像从一个ImageList我已经无法找到适当的解决问题的办法。

我已经有了一个定义列表视图控制,其具有附着于这一事件为绘制的ListViewItems.这个那么呼叫一个静态的方法,其设计绘制项目。

对于一个列表视图的大约300个项目,我们正在存储器中跳起来周围的100mb每次列表视图是滚动。违规的代码已经追查到如下:

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),垃圾收集工作不正常,导致了存储器,螺旋。我们已经尝试增加一个图像。Dispose()直接后块代码解决这个问题,但是,这并不具有任何效果。

唯一的解决办法,我已经找到迄今为止,是在结束静态的方法叫GC。收集().这个问题,但是它然后原因列表视图重新油漆本身慢慢并最终获得的文物在屏幕的同时,它试图重新绘制。

有任何人经历过这个?或者知道的一个解决方法?

有帮助吗?

解决方案

你处置 graphics?此外,它处理你的图像喜欢你提到那么你会需要确保它取出来的ImageList或者您将会导致更多的问题。什么什么格式的图像?

一般当你出去的记忆的问题时,图像都参与了,你的问题将是有些方法并不像一些图像的格式,或9/10的时候,你误解生命周期的一个图形象。

  • 检查所有你的 Graphics 使用,并把它们放在 using 块。
  • 检查你的 Image 生命周期的要小心将它们复制,处理他们关闭基础流,等等。
  • 载了存储管理(VS2008有一个建立在),并看看有什么是得不到清理得很好。

编辑:

这里是最好的选择我可以找到、使用 ImageList.画(graphics, x, y, width, height, index).这将使用内部处理,而不是创建一个副本的图像。

其他提示

我设法在我的应用程序来解决这个问题。

杰森有答案,你必须确保你使用“使用”块或其等价物。

我用VB,和等效是使用的try ... catch ...最后每当我创建了一个新的位图,呼吁BitMap.Dispose和设置在“最后”的一部分位图=什么都没有。

这似乎是一个很常见的问题,从我花了试图谷歌这个时间判断。下面还代码允许任何图像保持其宽高比被减少到一个缩略图时,这似乎是难以谷歌的另一个问题!

代码:

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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top