Question

Je travaille sur un projet à grande échelle où une coutume (assez bonne et robuste) cadre a été fourni et nous devons l'utiliser pour montrer des formulaires et des vues.


Il est classe abstraite StrategyEditor (dérivée d'une certaine classe dans le cadre) qui est instancié chaque fois qu'un nouveau StrategyForm est ouvert.

StrategyForm (un cadre de fenêtre sur mesure) contient StrategyEditor.
StrategyEditor contient StrategyTab.
StrategyTab contient StrategyCanvas.

Ceci est une petite partie des grandes classes pour préciser qu'il ya beaucoup d'objets qui seront créés si un objet StrategyForm est attribué en mémoire lors de l'exécution. Mon composant possède toutes ces classes mentionnées ci-dessus, sauf StrategyForm dont le code est pas dans mon contrôle.


Maintenant, à moment de l'exécution, l'utilisateur ouvre de nombreux objets de stratégie (dont la création de déclenchement de nouvel objet StrategyForm.) Après avoir créé environ. 44 objets de stratégie, nous voyons que les POIGNEES objet utilisateur (je vais utiliser UOH partir d'ici) créé par le cours d'application à environ 20k +, alors que dans le registre le montant par défaut pour les poignées est 10k. En savoir plus sur l'utilisateur Objets ici de. Test sur différentes machines a clairement indiqué que le nombre de la stratégie des objets ouverts est différent pour message pop-up -. sur un m / c si elle est 44, alors il peut être 40 sur un autre

Quand on voit pop-up le message, cela signifie que l'application va répondre lentement. Il y a pire avec quelques objets, puis la création de cadres de fenêtres et les objets suivants ne.

Nous avons d'abord pensé qu'il était question non suffisamment mémoire. Mais lire plus sur new en C # aidé à comprendre qu'une exception serait levée si l'application a manqué de mémoire. Ce n'est pas un problème de mémoire puis, je me sens (gestionnaire de tâches a également montré 1.5GB + mémoire disponible.)


spécifications M / C Core 2 Duo 2 GHz +
4 Go de RAM
80Go + espace disque disponible pour le fichier de page
jeu de mémoire virtuelle: 4000 - 6000
Mes questions


Q1. Est-ce que cela ressemble à un problème de mémoire et je me trompe que ce n'est pas?
Q2. Est-ce que ce point à l'épuisement des ÚOHS libres (comme je pense) et qui se traduit par l'échec de la création de poignées de fenêtres?
Q3. Comment pouvons-nous éviter de charger d'un objet StrategyEditor (au-delà d'un seuil, en gardant un œil sur l'utilisation actuelle de ÚOHS)? (Nous savons déjà comment récupérer nombre de ÚOHS utilisés, donc ne pas y aller.) Gardez à l'esprit que l'appel à new StrategyForm() est en dehors du contrôle de mon élément. Q4. Je suis peu confus - ce sont poignées pour les objets utilisateur exactement? Est MSDN parle tout objet que nous créons ou que certains objets spécifiques comme les poignées de fenêtre, les poignées de curseur, poignées icône
Q5. Quelles sont les causes exactement à utiliser un UOH? (Presque identique à Q4)

Je serais vraiment reconnaissant à tous ceux qui peuvent me donner des réponses bien informées. Merci beaucoup! :)

[Mise à jour] Sur la base de réponse Stakx, s'il vous plaît noter que les fenêtres qui sont en cours d'ouverture, seront fermés par l'utilisateur uniquement. Ce genre de situation est d'application MDI où trop de fenêtres pour enfants sont ouverts. Donc, Dispose ne peut pas être appelé à chaque fois que nous voulons.

Était-ce utile?

La solution

Q1

Sons comme vous essayez de créer beaucoup trop de contrôles d'interface utilisateur en même temps. Même si la mémoire, il est parti, vous êtes à court de poignées. Voir ci-dessous pour une brève, mais des explications assez technique.

Q4

Je comprends objet utilisateur pour être un objet qui fait partie de l'interface graphique. Au moins jusqu'à ce que Windows XP, l'API interface utilisateur de Windows réside dans USER.DLL (une des DLL de base composant de Windows). En fait, l'interface utilisateur est composée de « fenêtres ». Tous les contrôles, tels que les boutons, zones de texte, cases à cocher, sont à l'intérieur de la même chose, à savoir des « fenêtres ». Pour les créer, vous appelez la fonction API Win32 CreateWindow . Cette fonction serait alors renvoyer une poignée à la création « fenêtre » (élément d'interface utilisateur, ou « objet utilisateur »).

Je suppose que poignée d'objets utilisateur est une poignée retourné par cette fonction. (Winforms est basé sur l'ancienne API Win32 et serait donc utiliser la fonction CreateWindow.)

Q2

En effet, vous ne pouvez pas créer autant de contrôles de l'interface utilisateur que vous le souhaitez. Toutes les poignées récupérées par le moût de CreateWindow à un moment donné être libérés. En Winforms, la façon de faire est plus facile et plus sûr grâce à l'utilisation du bloc using ou en appelant Dispose:

using (MyForm form = new MyForm())
{
    if (form.ShowDialog() == DialogResult.OK) ...
}    

En gros, tout System.Windows.Forms.Control peut être Disposed, et doit être éliminé. Parfois, cela se fait automatiquement pour vous, mais vous ne devriez pas compter sur elle. Toujours Dispose vos contrôles de l'interface utilisateur lorsque vous ne avez plus besoin.

Note sur Dispose pour les formulaires modaux et modaux:

  • formes modales (montré avec ShowDialog) sont pas disposées automatiquement. Vous devez faire vous-même, comme le montre l'exemple de code ci-dessus.
  • formes modales (représentés avec Show) sont disposés automatiquement pour vous, puisque vous avez aucun contrôle sur quand il sera fermé par l'utilisateur. Pas besoin de Dispose explicitement appel!

Q5

Chaque fois que vous créez un objet de l'interface utilisateur, Winforms fait en interne les appels à CreateWindow. C'est ainsi que les poignées sont attribuées. Et ils ne sont pas libérés jusqu'à ce qu'un appel correspondant à DestroyWindow est fait. Dans Winforms, cet appel est déclenché par la méthode de l'une quelconque Dispose System.Windows.Forms.Control. (Note: Même si je suis certain farily à ce sujet, je devine en fait un peu que je ne peux pas être 100% correct Avoir un oeil à l'aide Winforms internals réflecteur révélerait la vérité...)

Q3

En supposant que votre StrategyEditor crée un groupe massif de commandes d'interface utilisateur, je ne pense pas que vous pouvez faire beaucoup. Si vous ne pouvez pas simplifier ce contrôle (par rapport au nombre de contrôles enfants qu'il crée), il semble que vous êtes coincé dans la situation où vous êtes. Il vous suffit de ne pouvez pas créer une infinité de contrôles d'interface utilisateur.

Vous pouvez cependant garder une trace de combien de StrategyEditors sont ouverts à tout moment (augmenter un compteur à chaque fois qu'un est instancié, et diminuer chaque fois que l'on est fermé - vous pouvez suivre ce dernier en utilisant l'événement FormClosing / FormClosed de un formulaire, ou dans le procédé de Dispose d'un témoin). Ensuite, vous pouvez limiter le nombre de StrategyEditors ouverts simultanément à un nombre fixe, par exemple 5. Si la limite est dépassée, vous pouvez lancer une exception dans le constructeur, de sorte que pas plus de cas sont créés. Bien sûr, je ne peux pas dire si StrategyForm va gérer une exception de votre puits constructeur StrategyEditor ...

public class StrategyEditor : ...
{
    public StrategyEditor()
    {
        InitializeComponent();

        if (numberOfLiveInstances >= maximumAllowedLiveInstances)
            throw ...;
        // not a nice solution IMHO, but if you've no other choice...
    }
}

Dans les deux cas, ce qui limite le nombre de StrategyEditors instanciés apparaît comme une solution temporaire pour moi et ne résoudra pas le problème réel.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top