从ImageList获取图像时,我遇到了OutOfMemoryException问题我一直无法找到解决此问题的适当方法。
我有一个自定义ListView控件,它附加了一个绘制ListViewItems的事件。然后调用一个静态方法,该方法用于绘制项目。
对于大约300个项目的ListView,每次滚动ListView时,我们的内存都会增加大约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上)垃圾收集不能正常工作,导致内存螺旋上升。我们尝试在代码块后面直接添加一个image.Dispose()来解决这个问题,但是没有任何效果。
到目前为止,我找到的唯一解决方案是在静态方法的末尾调用GC.Collect()。然而,这样做的问题是,它会导致ListView重新绘制自己的速度很慢,当它试图重新绘制时,屏幕上会出现工件。
还有没有人经历过这种情况?或者知道一种解决方法?
发布于 2009-05-20 04:42:56
你在处理graphics吗?此外,如果你像你提到的那样处理你的镜像,那么你需要确保它被从ImageList中取出,否则你会导致更多的问题。图像是什么格式的?
一般来说,当你遇到涉及图像的内存不足问题时,你的问题要么是某些方法不喜欢某些图像格式,要么是9/10次,你误解了其中一个图形对象的生命周期。
Graphics使用情况,并将其放入using块中。Image生命周期,并小心进行复制、处置、关闭基础流等。编辑:
这是我能找到的最好的选择,使用ImageList.Draw,x,y,width,height,index)`。这将使用内部句柄,而不是创建映像的副本。
发布于 2009-06-11 19:08:40
我已经设法在我的应用程序中解决了这个问题。
Jason给出了答案,你必须确保你使用了"using“块,或者它们的等价物。
我使用VB,等同于使用Try...抓住..。最后,每当我创建一个新的位图时,调用BitMap.Dispose并在" Finally“部分设置bitmap = nothing。
这似乎是一个非常常见的问题,从我花了几个小时在谷歌上搜索来判断。下面的代码还允许任何图像在缩小为缩略图时保持其纵横比,这是谷歌似乎很难解决的另一个问题!
代码:
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 Functionhttps://stackoverflow.com/questions/882619
复制相似问题