ResourceManager.GetObject() problem

Use this forum to read, ask or inform about memory issues in the .NET Framework and third party components.

Moderator: SciTech Software

ResourceManager.GetObject() problem

Postby Cybil74 » Wed Apr 22, 2009 11:39 am

Hi,
considering the following environment:

.NET Memory Profiler 3.1 with Dispose Tracker activated
Visual Studio 2005
.NET Framework 2.0

and the following C# code snippet:

Bitmap bitmap = (Bitmap)resourceManager.GetObject("MyBitmapName", cultureInfo);

I'm rather confused as if the returned bitmap should be disposed after use. Here are some elements I've collected about this topic.


1)
MSDN documentation states:
"Performance Considerations: if you call the GetObject method multiple times with the same name parameter, do not depend on the return value being a reference to the same object. This is because the GetObject method can return a reference to an existing resource object in a cache, or can reload the resource and return a reference to a new resource object."

The fact that, according to MSDN, calling ResourceManager.GetObject() multiple times with the same arguments could potentially return the same object again and again, could lead to think that a ResourceManager object acts as a shared resources pool manager. In that case, no Dispose() should be called against the returned bitmap because only the bitmap owner (i.e. the very ResourceManager) would ever be allowed to dispose a resource residing in its resource pool.

2)
But, according to my tests, ResourceManager.GetObject() never returns the same object, instead always a different one, when called with the same arguments. I've executed about 1000 ResourceManager.Getobject("MyBitmapName", cultureInfo), then programmatically compared the returned bitmap references by using object.ReferenceEquals(), and it never found even only two bitmap references that referenced the same bitmap in memory.

3)
If you create a localized Windows Forms, you will see that in the automatically generated Forms.InitializeComponent() method, a local ResourceManager is istantiated to let the localized resources of the Form to be loaded. The reference to that ResourceManager is just local, though, so the ResourceManager will be garbage collected sooner or later, while Form components will still be using its resources.
Now, following is the MSDN documentation of the ResourceManager.ReleaseAllResources() method:

"This method can also be used in situations where the managed instances for these resources created by the current ResourceManager have to be released deterministically, without waiting for the ResourceManager to go completely out of scope and be garbage collected"

That leads to think that, once the ResourceManger goes out of scope, by means of its finalizer the ResourceManager.ReleaseAllResources() method gets called, which in turn disposes all the resources residing in the resource pool of the ResourceManager. But that would lead to a disaster if those resources were still in use by the Form, as it is the actual case if you examine the Form.InitializeComponent() method.

4)
So, taking into account the above considerations, I would be lead to think that ResourceManger.GetObject() always returns a new instance of a resource when called with the same arguments, and that it is responsibility of the caller to dispose the returned resources

5)
But, executing

Bitmap bitmap = (Bitmap)resourceManager.GetObject("MyBitmapName", cultureInfo);
.
.
.
bitmap.Dispose()

.NET Memory Profiler detects an instance that has been disposed but is still alive, which could be a dangerous situation. Of course that instance has been disposed by me with the above line; after some investigation, I found out that the pending reference is hold by an internal member of the ResourceManager class.

6)
So, after all these considerations, I ask anyone which is the correct use pattern of the ResourceManager.GetObject() method

Thank you in advance
Cybil74
 
Posts: 3
Joined: Wed Apr 22, 2009 8:45 am

Postby Andreas Suurkuusk » Thu Apr 23, 2009 9:48 pm

The ResourceManager class lacks a clear definition of who owns the provided resource instances. As the documentation state, you may or may not get a new instance when you request the same resource. So you cannot safely dispose disposable instances returned by a ResourceManager, since they might get reused.

There are several implementations of the ResourceManager, and several ways to initialize the resources in a ResourceManager. The ResourceManager used in a WinForms control is based on a binary resource stream. As far as I know, types like Bitmap will not be cached by this ResourceManager and a new Bitmap will be returned each time (it's being deserialized from the resource stream on each request).

Other ResourceManagers might be initialized by an IResourceReader. In this case, all resources provided by the IResourceReader will just be added to a hashtable. Requesting the same resource, will always return the same instance.

Releasing the resources from a ResourceManager will close any underlying streams, and clear the caches, but disposable instances will not be disposed.

So unfortunately, if a ResourceManager is used it's hard to avoid undisposed instances.
Best regards,

Andreas Suurkuusk
SciTech Software AB
Andreas Suurkuusk
 
Posts: 964
Joined: Wed Mar 02, 2005 7:53 pm
Location: Sweden

Re: ResourceManager.GetObject() problem

Postby nicolbiden » Thu Jun 04, 2015 6:09 am

Check with.....Culture Info

Biden
nicolbiden
 
Posts: 1
Joined: Thu Jun 04, 2015 6:06 am


Return to Known Memory Issues

Who is online

Users browsing this forum: No registered users and 1 guest

SciTech Software logo

© Copyright 2001-2016. SciTech Software AB
All rights reserved.


SciTech Software AB
Kartvägen 21
SE-175 46 Järfälla
Sweden


E-mail: mail@scitech.se

Telephone: +46-706868081

cron