Visual Studio 2010中的内存不足问题Visual Basic .NET 4.0

问题描述:

我有两个Windows窗体程序,它是一个图片数据库和幻灯片放映。所述Visual Studio 2010中的内存不足问题Visual Basic .NET 4.0

幻灯片连续地更新所显示的图片框,而不递增与画面的每个新的交换机中使用的

存储器。但是,我有第二种形式,

有50个图片框,旨在显示要添加到数据库的图片的缩略图。由于每个尺寸为(57,40)的图片盒都使用小尺寸缩略图(< 12K)进行更新,因此在32位XP系统上IDE使用的内存略高于1GB,从加载任何缩略图图片盒之前的约660MB 。

从.jpg源文件加载大约30个大小(57,40)的pictureboxes到大于3MB,IDE内存使用量增加到大约2.1GB。 (问题不容易遇到.jpg图像< = 15K和所有50个缩略图可与<使用1.3 GB内存使用)。

问题显示自身的平均.jpg文件大小大于3MB的图像每个高清佳能相机.jpg图像被加载到30个显示的缩略图pictureboxes,我开始点击左右选择显示的图片和使用内存快速上升,超过2.3GB的内存使用率导致内存不足崩溃。

这是VB2010或.NET 4.0中的错误吗?

将所有图片以缩略图形式显示后,鼠标单击包含所有缩略图的面板上的50个图片框中的任意一个,即可更新图片上的单个大型图片箱,以在单个图片框中显示图片, 1024,768)。当单击任何缩略图时,单个大图片框会显示来自文件的相关图片,但与此同时,系统内存每增加约240KB的点击事件。最终,在大约2.3GB的系统内存使用情况下,程序崩溃并出现内存不足错误。

我怎样才能得到程序时

它与只是另一张照片更新到恢复由相同图片框使用的内存?

部分代码如下:

' Each Thumbnail has a click event 
'PB49 is a PictureBox max size (57,40) used as a thumbnail display, all 50 are on a panel 
Private Sub PB49_Click(sender As System.Object, e As System.EventArgs) Handles PB49.Click 
    'PB(50) is an Integer Array flagging Pictures to add 
    If PB(49) = 1 Then PB(49) = 0 Else PB(49) = 1 
    If PB(49) = 1 Then 
     CheckBox49.Checked = True  'Tiny Checkbox on thumbnail 
     F$ = ListAddFiles.Items(48)  'ListFileBox of FileNames 
     PBx1.Image = Image.FromFile(F$) 'Gets filename and path and loads image into PictureBox 
     PBx1.Visible = True 'Large PictureBox (1024,768)shows Pic F$ located on Form 
    Else 
     CheckBox49.Checked = False 
     PBx1.Image = Nothing 
     PBx1.Visible = False 
    End If 
End Sub 

我使用上安装XP PRO 32-Bit SP3 4GB RAMVisual Studio Ultimate SP1 updated .NET 4.0

+0

你处置了需要配置的对象? –

+0

你不应该在你的问题中使用这么多'?'。 – VMAtm

+0

这绝对是你的错误,而不是VS. – VMAtm

当您隐藏图像时,是否有可能再次加载图像。即你将它隐藏起来,而隐藏的那个会留在那里,并在稍后再次添加。因此,你正在积累大量的隐藏图像?

.NET应用程序中的“内存泄漏”通常是由于没有清除引用或从所有集合中删除对象而导致的结果。只要某个对象具有某个地方的引用,无论是某个表单的控件集合中的某个控件还是您自己的集合中的某个控件,它都将保留在内存中。我不确定你的逻辑是用于显示/隐藏图片,但也许你需要删除图片,并确保你清除所有相关控件的引用。控制集合可以嵌套的方式,很容易错过一个地方。图像相关的控件可能会带来很多额外的开销,所以如果你有很多未使用的控件隐藏在内存中,那么这可能是一个问题。

你说你有50个图片框,但是你有更多的图片比集合中没有显示的图片。如果你已经将它们加载到一个集合中,那么无论它们是否被显示,它们都可能占用内存。

夫妇的事情要注意。

1)32位Windows中的进程最多可用2GB内存。有一些方法可以在一台机器上将其配置为3GB,但通常不应该指望拥有超过2GB的可用空间。 Ojn最重要的是,通常的内存碎片可能会导致您出现OutOfMemory异常,即使看起来您拥有大量可用内存。

2)当你处理.NET集合时,通常在内部它们被实现为数组。数组是连续的内存块。因此,即使有足够的可用内存,也可能会发生OutOfMemory异常,因为没有足够的连续内存块(由于碎片)。 .NET试图减少fragementation,但有时候就像在一个拥挤的房间里移动一个巨大的桌子一样,它不能创造奇迹。 3)由于数组不会动态扩展,因此集合内部必须在空间不足时分配新数组。通常每次都会使数组大小加倍。这是大多数收藏的“.Capacity”属性。您应该使用一些调试来监视集合的.Capacity和.Length。每当收藏达到这个尺寸时,您都会观察它。即128,256等

每当它加倍时,它必须分配一个新数组,然后在释放旧数组之前复制旧数组的内容。因此,如果你有一个拥有256个(或者其他权力为2个像64个)项目的集合,然后再添加一个项目,那么集合在内部分配一个新的512项目数组,然后从前一个数组复制到它。在这个过渡过程中,你在内存中都有一个512和256的数组。所以虽然你只需要257个物品的空间,但添加第257个物品需要三倍的空间(256 + 512 = 768)。

您可以使用堆栈跟踪来确定在尝试向收集中添加图片时是否发生异常,因为它在调用中添加了时间,该时间是收集如果需要时展开的地方。你还会注意到在调用之前的长度将是2的幂。

所以如果你有512MB的图像并且集合需要扩展以增加一个,.NET必须找到空间来分配一个1GB的数组的图像。所以在这个系列的扩展过程中,它需要1.5G的RAM。对于.NET而言,由于碎片,找到一个1gb的ram连续块是非常困难的,即使所有的步骤.NET尽量减少碎片,但仍然有很多控制。 (有人可能会指出,引用数组要小得多,但很难说什么你正在处理。)

解决方案: 如果你确定这是你的问题的原因,然后解决方案预测您将需要多少物品,并预先设置阵列的容量。因此,如果您有一张图像列表,那么最好首先计算这些图像的数量,然后将集合的容量设置为该数量,并且可能再加上10%或更多。这样,如果您有300件物品,则可以将容量设置为350.这样,您可以预先使用一个小顶部空间来预估容量,那么它将永远不会扩展,因此不会经历3倍的峰值内存使用情况进行扩展。

Google .NET内存分析器。有很多配置文件,也赢得调试,可以让你看到内存分配和重新分配的细节以及碎片。

+0

在代码中发现问题。 – VMAtm

@AaronLS给了一个终极热情的答案,所以阅读并记住它。
在你的代码中的内存泄漏是在这里:

PBx1.Image = Nothing 
PBx1.Visible = False 

PBx1.Image是Image类型的对象,当您使用Image.FromFile方法。而ImageIDisposable,这意味着它在非托管代码中使用本地资源。

您必须显式调用PBX1的.Dispose()方法在此代码:

'PBx1.Image = Nothing 
If PBx1.Image IsNot Nothing Then PBx1.Image.Dispose() End If 
PBx1.Visible = False