开发者

How c# handles memory

开发者 https://www.devze.com 2022-12-16 18:39 出处:网络
I have a class \"skImage\". This class has a private variable (with a public property that exposes it)

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


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;


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


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


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?


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号