6
votes

Obtenir une image par ResourceManager GetObject - Appelez-le à chaque fois ou stockez le résultat?

Disons que je dois montrer des graphiques sur certains contrôles. Mais il y aura trois images commutées en fonction de certaines conditions. Trois bitmap sont ajoutés dans le fichier de ressources.

Alors, je les récupère en appelant ResourceManager.getObject.

La question est que cela devrait être:

  1. chaque fois que je dois changer d'image, j'appelle GetObject pour l'obtenir et attribuer au contrôle ou
  2. Tenez le résultat de GetObject pour chaque image au début, de sorte qu'il n'y a jamais de 3 appels à GetObject. Attribuer une image de mes variables à la place.

    faire 1) semble produire beaucoup de poignée GC lors de la visualisation avec le profileur CLR. Dans l'espoir de connaître un effet secondaire mauvais de 2).

    Merci beaucoup.


0 commentaires

5 Réponses :


8
votes

Chaque appel à getObject lira l'image de l'assemblage et chargez-la dans un objet bitmap bitmap .

L'appelant plusieurs fois créera des frais généraux importants; Vous devez stocker les images.


0 commentaires

1
votes

Le Documentation MSDN indique que la valeur de la ressource est renvoyée par ResourceManager.getObject. Comme il ressemble à des bitmaps individuels ne change pas à l'heure, le seul côté bas que je vois à approcher # 2 est que votre empreinte mémoire sera un peu plus grande.


0 commentaires

4
votes

Une autre chose à souligner à propos de l'appelant "ResourceManager.GetObject" Chaque fois que vous devez utiliser une image à partir de ressources, il semble qu'il semble créer une nouvelle poignée de Windows à chaque fois. Dans votre cas, probablement pas un gros problème, mais si vous y teniez-y pendant un moment, comme nous l'avons fait pourraient causer un problème.

Nous avions un datagridView que nous poussions des images à partir de ressources dans différents domaines de la grille et que la grille a augmenté de plus de 3000 rangées, nous dépassions réellement les poignées Windows maximales autorisées pour un programme 32 bits.

L'erreur est apparue une argument aléatoire Exceptions avec message "Le paramètre n'est pas valide". Il a fallu quelques heures à penser que nous avions une fuite de mémoire mais a finalement trouvé ce que nous avons chargé cette interface graphique avec cette grille les poignées d'applications passées de 700 à 1 000 à plus de 10k avant même de finir le chargement et ne pouvaient pas récupérer l'ensemble du programme et ne pouvaient pas récupérer. Donc, je recommande l'option 2 ici.


0 commentaires

2
votes

J'ai également implémenté le "Lire une fois, puis stockez dans la variable" Concept dans mes classes.

à Donnez un exemple, voici un extrait de mon code: xxx

peut-être que cela aide quelqu'un un jour.


0 commentaires

5
votes

J'ai une application WinForms qui utilise de nombreuses instances des mêmes formulaires, chacune avec de nombreuses images et icônes pour menus et boutons et tels. Toutes ces images sont stockées dans le [ProjectName] généré automatiquement .properties.Resources code> classe.

J'ai remarqué que l'utilisation de la mémoire était terriblement élevée; Après seulement 10 instances de formes, il utilisait plusieurs centaines de MBS de mémoire et traverserait facilement 1 Go facilement après plusieurs autres instances. J'ai tracé la question à la méthode ResourSemanager.getObject code>. La méthode code> getObject getObject renvoie une nouvelle instance de chaque objet demandé, ce qui me semblait tort. P>

Au lieu de laisser toutes ces instances d'images tremper la mémoire que de tomber hors de portée, pourquoi ne pas les réutiliser pour des instances de forme futures? Donc, j'ai créé une classe Cachedesourcemananger Cache> Classe et remplacer les méthodes getObject code> pour renvoyer les instances en cache des objets demandés. P>

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


0 commentaires