首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ImageList /图像OutOfMemoryException

ImageList /图像OutOfMemoryException
EN

Stack Overflow用户
提问于 2009-05-19 13:00:31
回答 2查看 3.6K关注 0票数 4

从ImageList获取图像时,我遇到了OutOfMemoryException问题我一直无法找到解决此问题的适当方法。

我有一个自定义ListView控件,它附加了一个绘制ListViewItems的事件。然后调用一个静态方法,该方法用于绘制项目。

对于大约300个项目的ListView,每次滚动ListView时,我们的内存都会增加大约100Mb。违规代码已被追踪到以下几点:

代码语言:javascript
复制
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重新绘制自己的速度很慢,当它试图重新绘制时,屏幕上会出现工件。

还有没有人经历过这种情况?或者知道一种解决方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-05-20 04:42:56

你在处理graphics吗?此外,如果你像你提到的那样处理你的镜像,那么你需要确保它被从ImageList中取出,否则你会导致更多的问题。图像是什么格式的?

一般来说,当你遇到涉及图像的内存不足问题时,你的问题要么是某些方法不喜欢某些图像格式,要么是9/10次,你误解了其中一个图形对象的生命周期。

  • 检查您的所有Graphics使用情况,并将其放入using块中。
  • 检查您的Image生命周期,并小心进行复制、处置、关闭基础流等。
  • 加载内存管理器(VS2008具有内置的内存管理器),并查看哪些内存管理器未得到很好的清理。<代码>H210<代码>F211

编辑:

这是我能找到的最好的选择,使用ImageList.Draw,x,y,width,height,index)`。这将使用内部句柄,而不是创建映像的副本。

票数 4
EN

Stack Overflow用户

发布于 2009-06-11 19:08:40

我已经设法在我的应用程序中解决了这个问题。

Jason给出了答案,你必须确保你使用了"using“块,或者它们的等价物。

我使用VB,等同于使用Try...抓住..。最后,每当我创建一个新的位图时,调用BitMap.Dispose并在" Finally“部分设置bitmap = nothing。

这似乎是一个非常常见的问题,从我花了几个小时在谷歌上搜索来判断。下面的代码还允许任何图像在缩小为缩略图时保持其纵横比,这是谷歌似乎很难解决的另一个问题!

代码:

代码语言:javascript
复制
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
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/882619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档