views:

101

answers:

4

I have a complex program in which I have to first create, then use wrappers around bitmaps and send them across a lot of different classes. The problem in the end is deciding which classes should dispose the bitmaps. Most of the time the end classes don't know if they can indeed dispose the bitmap as the same bitmap can be used in several places. Also, I can't just copy the bitmaps because this is a kind of resource intensive algorithm and doing it would be dead slow.

I looked up on reflector for Image/Bitmap's implementations and they seem to use the Dispose Pattern. So, even if I don't call Dispose(), the CLR will eventually call it some other time.

Is it too bad if I just let the bitmaps be as they are, and let the finalizer take care of them?

+1  A: 

So, even if I don't call Dispose(), the CLR will eventually call it some other time.

The Finalizer and the Dispose method are two different things. It "should" do this, but you can't say for certain that it will. You can't assume this, you'll have to check on a case by case basis. From what you say, in this case it sounds like it does.

Is it too bad if I just let the bitmaps be as they are, and let the finalizer take care of them?

Yes it is, because specifying a finalizer causes extra work for the Garbage Collector. It will automatically promote it to the next generation of the CG, meaning resources won't be released as soon as they could. Normally, when someone implements Dispose they suppress the finalizer call which will prevent this.

Anytime an object implements IDisposable, it should be encased in a using statement.

using(var bitmap = new BitMap())
{
....

}

In this case, since the dispose method is in the finalizer, and you really really need to, you can not use the dispose method and let the finalizer take care of it. It's not good, but you can do it. Based on what you say, this may be the best course of action without refactoring the code.

Kevin
About the first point, yes I can, as the finalizer is calling the Dispose() method.
devoured elysium
About the second point, maybe the resources won't be released as soon as they should, but that is def preferable than having do make a complex design just to get rid of the bitmaps, I'd say.
devoured elysium
@devoured elysium: It shouldn't be a complex design. You likely already know when you're getting rid of the image (when you set it to null), so you just call `.Dispose()` before setting it to null.
Will Eddins
@Will: setting a (1) reference to null isn't the right condition.
Henk Holterman
No, you're right, it's after there are no more references. Typically with images, I'm used to having only a single reference (inside the displaying object, often the last image shown when doing updates), so I insert the new and dispose the old.
Will Eddins
A: 

What is the lifetime of the bitmaps? In other words, what triggers the creation of the bitmaps and what "events" take place between then and when they can be safely destroyed?

If there are no user/external events taking place between creation and end of life, it would be best if the code could be structured such that the code that creates the bitmaps also destroys them.

In C#, it would be best to wrap them in a using statement:

using (Bitmap bitmap = CreateBitmap())
{
    DoWork(bitmap);
}

This guarantees that the bitmap is only retained for as long as it is needed and no more.

If user/external events occur between creation and end of life (and the bitmaps need to be accessed in the processing opf those events), the situation is not this simple but this would also imply that you're keeping a persistant reference to the bitmaps somewhere which would prevent them from being garbage collected anyway.

Daniel Renshaw
As I've said, I have to use them in a lot of places. I can't just wrap them with using tags.
devoured elysium
But are all those "lot of places" all in the same call stack above the point where the bitmaps are created or are they spread over multiuple threads/multiple web requests/multiple UI events?
Daniel Renshaw
Multiple UI events and multiple threads.
devoured elysium
In that case they'll never be finalised/garbage collected unless you're explicitly removing whatever fields/cache is referencing them and, if you're doing that, then you can simply call dispose just before dereferencing the objects - that would be a lot more efficient than relying on the garbage collector calling the finaliser.
Daniel Renshaw
You have multiple UI events and threads; the instance members of the Bitmap class are not guaranteed to be thread safe. How are you synchronizing access to your common instances?
Michael Petito
+1  A: 

Your main problem here seems to be your design, but it is probably too late and/or too expensive to fix now. But in general, avoid holding on to resources for too long.

Since you are using wrappers, you could take a look at reference counting as a design pattern. Any holding object could register & unregister its interest in the bitmap and you can Dispose when the ref count drops to 0.

But the easy way here is to just let the GC do the work. Just make sure all referencing fields to the wrappers are null-ed asap.

Henk Holterman
A: 

Well based on what I understood from your question I would suggest you following

Extend the IDisposable interface in the classes in which you are retaining the class level variable of the image object and dispose that image object in the Dispose() method.

I also think that you do not need to worry about the bitmap object you are passing to other methods, you do not need to dispose it in that specific class. Just make sure you are disposing it in the class which is creating the instance of the bitmap.

Hope this will help you.

Ram