2010-01-15 55 views
2

我有一个类“skImage”。这个类有一个私有变量(与公开它的公共属性)c#如何处理内存

private Image _capturedImage; 

这个类的构造函数的样子:

public skImage(Image captured) { 

      _capturedImage = captured; 

     } 

它还具有以下方法:

public bool Invert() { 

     Bitmap b = new Bitmap(_capturedImage); 

     unsafe { 
     //random code not relevant. 
     } 

     _capturedImage = b; 
     b.Dispose(); 
     return true; 
    } 

然后它有一个save()方法,它只是调用:

_capturedImage.Save(_saveFullLocation); 

现在,如果我运行翻转方法,然后尝试调用保存它会引发异常(参数无效)。谷歌搜索这个例外后,似乎我正在处理图像。我可以看到,我在倒置方法之后部署了“b”。

我的问题是,当我做_capturedImage = b这是否意味着这两个变量现在持有一个对象的引用?我不想那样。我希望b被销毁以减轻记忆,因此GC可以收集它。我如何将b传递给_capturedImage并销毁b。

感谢

回答

3

这是否意味着这两个变量现在持有一个对象的引用?

是的。然而,参考只是一个参考 - 它不会花费太多的内存。

我希望B被摧毁

你不能摧毁一个参考 - 你只能处理对象本身。

相反处置B您应该写的:

_capturedImage.Dispose(); 
_capturedImage = b; 
+0

将意味着当b超出范围(即方法已完成)GC将收集b并释放与其关联的所有内存? – masfenix 2010-01-15 19:09:22

+0

@masfenix - 引用b在Invert方法的堆栈框架上创建 - 当该方法返回时,b将不再存在。但是,b引用的对象(位图)仍将存在于堆上(直到它被垃圾收集为止)。 – mbeckish 2010-01-15 19:13:20

+0

要添加到mbeckish的评论中,该对象将不会被垃圾收集(嗯,现在不是),因为位图仍然由_capturedImage指向。 – Brian 2010-01-15 19:17:23

-2

image.Clone()

你必须把结果给您的数据再次输入,虽然因为clone()返回一个System.Object。

编辑:我一定误解了这个问题。我以为你想要一个无法在其他地方被代码处置的图像。只要您在内存中共享对同一图像的引用,其他所有意识到该图像的人都可以处理该图像,从而有效地将您搞砸。通过克隆映像,确保没有其他人(或您编写的其他代码)可以处理它。

+0

我该怎么克隆?而不是_capturedImage = b,我应该做_capturedImage = b.clone(); ?? – masfenix 2010-01-15 19:05:29

+0

为什么克隆图像? – Matthias 2010-01-15 19:05:48

+1

-1:克隆一个物体并处理原物几乎肯定是一种愚蠢的行为。 – Brian 2010-01-15 19:07:35

2

_capturedImage和b是相同的基础对象引用。调用b.Dispose();也会处理_capturedImage,因为它们都是指向相同数据块的引用。一旦b超出范围(即Invert返回),b将停止存在,但GC将不会收集数据,因为_capturedImage仍指向它。

0

正如其他人所提到的,您正在将b和_capturedImage指向同一个对象,因此当您处理b时,_capturedImage也会显示出来。

我没有看到任何需要在这里调用Dipose()。该变量在函数的范围内声明,所以它将没有引用,GC将自动清除它。

事实上,我甚至不看为“B”变量的需要。你为什么不在整个函数中使用'_capturedImage'并且保持简单?

1

当你必须创建一个新的位图来替换另一个位图时,一般的经验法则是保存对旧位图的引用,将新引用保存到用于存储它的变量中,然后丢弃旧位图。

这样,你应该有相关的存储变量修改任何行为,避免“闪烁”。这通常用于双缓冲;

public bool Invert() 
{ 
    //this will create a clone of _captureImage, so you effectivly have 2 Bitmaps at that point 
    Bitmap b = new Bitmap(_capturedImage); 

    unsafe 
    { 
    //random code not relevant. 
    } 

    var old = _capturedImage; //store old reference 

    //assign, any events will seemlesly transition from the old to the new Bitmap 
    _capturedImage = b; 
    old.Dispose(); //get rid of the old Bitmap 

    return true; 
}