views:

135

answers:

5

I have a class "skImage". This class has a private variable (with a public property that exposes it)

private Image _capturedImage;  

the constructor of this class looks like:

   public skImage(Image captured) {

            _capturedImage = captured;

        }

It also has the following method:

public bool Invert() {

        Bitmap b = new Bitmap(_capturedImage);

        unsafe {
         //random code not relevant.
        }

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

and then it has a save() method, which just calls:

  _capturedImage.Save(_saveFullLocation);

now if i run the invert method and then try calling save it throws an exception (parameter is not valid). After googling this exception it seems like I am disposing of the image. I can see that I am disposing "b" after the invert method.

My question is that when i do _capturedImage = b does that mean both variables now hold one reference to the object? I dont want that. I want b to be destroyed to relieve memory so the GC can collect it. How do i transfer b to _capturedImage and destroy b.

thanks

A: 

image.Clone()

You'll have to cast the result to your data type again though since Clone() returns a System.Object.

Edit: I must have misunderstood the problem. I thought you wanted to have an image that could not get disposed by code elsewhere. As long as you share references to the same image in memory, everyone else who is aware of that image can dispose it, effectively screwing you over. By cloning the image you ensure that nobody else (or some other code you wrote) can dispose it.

David Rutten
what do I clone? instead of _capturedImage = b, should I do _capturedImage = b.clone();??
masfenix
Why cloning the image?
winSharp93
-1: Cloning an object and disposing of the original is almost definitely a foolish.
Brian
+3  A: 

does that mean both variables now hold one reference to the object?

Yes. However, a reference is only a reference - it does not cost much memory.

I want b to be destroyed

You cannot destroy a reference - you can only dispose the object itself.

Instead of disposing b you should write:

_capturedImage.Dispose();
_capturedImage = b;
winSharp93
will that mean when b is out of scope (ie the method has finished) GC will collect b and release all memory associated to it?
masfenix
@masfenix - The reference b is created on the stack frame of the Invert method - when that method returns, b will no longer exist. However, the object to which b refers (the Bitmap) will still exist on the heap (until it is garbage collected).
mbeckish
To add to mbeckish's comment, that object will not be garbage collected (well, not right now) because the bitmap is still pointed to by _capturedImage.
Brian
@masefix: Why do you want to get rid of the image referenced by b?!? You have stored it in _saveFullLocation so you still need it! It's the same bitmap you dispose and want to save.
winSharp93
+2  A: 

_capturedImage and b are references to the same underlying object. Calling b.Dispose(); will also dispose of _capturedImage, since they are both references which point to the same blob of data. Once b is out of scope (i.e. when Invert returns), b will stop existing but the GC will not collect the data since _capturedImage still points to it.

Brian
A: 

As others have mentioned, you're making b and _capturedImage point to the same object, so when you Dispose of b, _capturedImage is diposed too.

I don't see any need to call Dipose() here. The variable is declared in the scope of the function, so it will have no references and the GC will clean it up automatically.

In fact, I don't even see the need for the 'b' variable. Why don't you just use '_capturedImage' throughout the whole function and keep things simple?

dferraro
+1  A: 

A general rule of thumb when you have to create a new Bitmap to replace another is to save the reference to the old Bitmap, assign the new one to the variable you use to store it, then dispose the old one.

This way, should you have any behavior related to the modification of the storing variable, you avoid "flickering". This is commonly used in double-buffering;

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;
}
Dynami Le Savard