masfenix
masfenix

Reputation: 8016

How c# handles memory

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

Upvotes: 2

Views: 1001

Answers (5)

Dynami Le Savard
Dynami Le Savard

Reputation: 5036

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;
}

Upvotes: 1

David Rutten
David Rutten

Reputation: 4806

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.

Upvotes: -2

dferraro
dferraro

Reputation: 6438

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?

Upvotes: 0

Brian
Brian

Reputation: 25834

_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.

Upvotes: 2

Matthias
Matthias

Reputation: 12259

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;

Upvotes: 3

Related Questions