Getting an image using the ResourceManager GetObject - calling it every time or saving the result?

Let's say that I have to show some graphs on some kind of control. But there will be three images switched based on some condition. Three raster images are added to the resource file.

So, I retrieve them by calling ResourceManager.GetObject.

The question is if this is:

  • Every time I have to switch an image, I call GetObject to get it and assign it to the control or
  • hold the GetObject result for each image at the beginning, so there will be only 3 calls in GetObject. Instead, assign an image from my variables.

Performing 1) seems to create a lot of GC pens when viewed with the CLR Profiler. Hoping to find out any bad side effect 2).

Many thanks.

+5
source share
5 answers

Each call GetObjectwill read the image from the assembly and load it into the object Bitmap.

Calling it many times creates significant overhead; You must store images.

+6
source

, "ResourceManager.GetObject" , "", , Windows. , , , - , , .

DataGridView, , 3000 , Windows 32- .

" ". , , , , , , , 700-1000 10 000, , . 2 .

+3

" , " concept .

, :

internal static class MyResourcesHolder
{
    private static Image _i1;
    private static Image _i2;
    private static Image _i3;
    private static Image _i4;
    private static Image _i5;

    public static Image MyImage01 => _i1 ?? (_i1 = Resources.MyImage01);
    public static Image MyImage02 => _i2 ?? (_i2 = Resources.MyImage02);
    public static Image MyImage03 => _i3 ?? (_i3 = Resources.MyImage03);
    public static Image MyImage04 => _i4 ?? (_i4 = Resources.MyImage04);
    public static Image MyImage05 => _i5 ?? (_i5 = Resources.MyImage05);
}

, - .

+2

MSDN , ResourceManager.GetObject. , , , 2, , .

+1

WinForms, , . [ProjectName].Properties.Resources.

, ; 10 Form 1+ GB . ResourceManager.GetObject. GetObject , .

, , , Form? CachedResourceMananger GetObject GetObject .

 /// <summary>
/// A custom Resource Manager that provides cached instances of objects.
/// This differs from the stock ResourceManager class which always
/// deserializes and creates new instances of every object.
/// After the first time an object is requested, it will be cached
/// for all future requests.
/// </summary>
public class CachedResourceManager : System.Resources.ResourceManager
{
    /// <summary>
    /// A hashtable is used to store the objects.
    /// </summary>
    private Hashtable objectCache = new Hashtable();

    public CachedResourceManager(Type resourceSource) : base(resourceSource)
    {
    }

    public CachedResourceManager(string baseName, Assembly assembly) : base(baseName, assembly)
    {
    }

    public CachedResourceManager(string baseName, Assembly assembly, Type usingResourceSet) : base(baseName, assembly, usingResourceSet)
    {
    }

    public CachedResourceManager() : base()
    {
    }

    /// <summary>
    /// Returns a cached instance of the specified resource.
    /// </summary>
    public override object GetObject(string name)
    {
        return GetObject(name, null);
    }

    /// <summary>
    /// Returns a cached instance of the specified resource.
    /// </summary>
    public override object GetObject(string name, CultureInfo culture)
    {
        // Try to get the specified object from the cache.
        var obj = objectCache[name];

        // If the object has not been cached, add it
        // and return a cached instance.
        if (obj == null)
        {
            objectCache[name] = base.GetObject(name, culture);
            obj = objectCache[name];
        }

        return obj;
    }
}

Then I changed the property and resource manager field in automatically generated [ProjectName].Properties.Resourcesto use my own resource manager, replacing global::System.Resources.ResourceManagerwith CachedResourceManager.

internal class Resources
{
    private static CachedResourceManager resourceMan;

    private static global::System.Globalization.CultureInfo resourceCulture;

    [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
    internal Resources() {
    }

    /// <summary>
    ///   Returns the cached ResourceManager instance used by this class.
    /// </summary>
    [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
    internal static CachedResourceManager ResourceManager 
    {
        get {
               if (object.ReferenceEquals(resourceMan, null))
               {
                  CachedResourceManager temp = new CachedResourceManager("Project.Properties.Resources", typeof(Resources).Assembly);
                  resourceMan = temp;
               }
               return resourceMan;
            }
    }

    // Image/object properties for your resources

} // End of resources class

This significantly reduced memory usage and also significantly reduced the loading time for new instances of forms.

0
source

All Articles