c#singleton winform加载/卸载图像

时间:2012-08-27 21:25:35

标签: c# image singleton dispose idisposable

我有一个winform应用程序。主要形式是单身,它加载了很多图像。图像代表产品,每次点击图像,我都会修改产品库存并重新加载产品和图像的哈希表。

问题在于我每次从BBDD重新加载产品的哈希表并重新加载图像。在一天结束时,应用程序耗尽了大量内存,我不知道何时以及如何卸载图像以便重新加载(因为有时我可以修改图像,我也必须重新加载)

重新加载哈希表和按钮的代码是:

Family fam = new Family();

List<Family> listFamilies = fam.loadFamilies();
htProducts.Clear();

foreach(Family family in listFamilies)
{
   //reload all the products of each family
   if(htProducts[family.idFamily]==null)
   {
     List<Product> listProducts= fam.loadProductsFamily(family.idFamily);
     htProducts[family.idFamily] = listProducts;
   }
   Button bt = new Button();
   bt.location = new Point(x,y); //The buttons are created dinamically
   bt.Parent = panelFamilies;//I have all the buttons inside a panel.
   try
   {
      if(family.urlImage !="")
      {
         bt.Text=family.Name;
         bt.Image = new Bitmap(family.urlImage);
      }
   }
   catch(Exception ex)
   {
     ....
    }

}

当我点击“家庭”按钮时,它会加载该系列的产品,但代码或多或少相同。它也会加载图像。

更多的是,这是代码。问题是每次我点击一个按钮,我会在产品上加载更多按钮并加载图片。

很多时候我重新加载单例表单并执行前面的代码,再次加载图像并耗尽内存。

¿何时以及如何卸载图像?

编辑:

我在再次加载带图像的按钮之前添加了以下代码:

foreach (Control c in panel8.Controls)
{
    if (c is Button)
        c.Dispose();
}
GC.Collect(GC.MaxGeneration);// I think that isn't correct to use because I've read,  but reduces the memory.

它会处理面板的所有按钮和图像,并在再次加载图像之前减少内存?

对不起我的英文:(

非常感谢。

3 个答案:

答案 0 :(得分:2)

foreach (Control c in panel8.Controls)
{
    if (c is Button)
        c.Dispose();
}

那不行。通常,当您在循环集合的foreach语句中更改集合时,.NET集合类会引发InvalidOperationException。不幸的是,这没有为Controls集合实现。所以这段代码所做的只是处理所有其他控件。这足以导致不受控制的资源泄漏,不仅仅是Button控件,还有他们的图像。

修复是向后迭代Controls集合,如下所示:

for (int ix = panel8.Controls.Count - 1; ix >= 0; --ix) {
    Control c = panel8.Controls[ix];
    // etc...
}

答案 1 :(得分:1)

听起来你在表格中持有一两个参考。

您应该使用像CLRProfiler或ANT这样的调试器来查看您的过程,以了解在您的过程中占用如此多内存的内容。获得此信息后,您可以采取下一步措施,确保释放所有引用信息,以便收集信息。

答案 2 :(得分:1)

要进行问题排查,请致电

GC.Collect(GC.MaxGeneration);

这将强制垃圾收集。然后在进程资源管理器或任务管理器中检查内存使用情况。如果它更小,它只意味着运行时决定不收集内存。

如果它不起作用,则需要找到内存泄漏。