IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Windows Forms Discussion :

[C#]Libération des ressources


Sujet :

Windows Forms

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2008
    Messages : 612
    Par défaut [C#]Libération des ressources
    Bonjour,

    Je suis toujours un peu dubitatif au sujet de la libération des ressources. En fait, je ne vois pas bien de façon intuitive quand je dois ou non m'occuper explicitement de libérer les ressources utilisées, et sur le net je trouve des exemples qui me semblent contradictoires.

    Par exemple, si je dérive un RichTextBox, et que dans ce contrôle dérivé j'ai créé un menu interne.

    Dois-je ajouter ceci à mon contrôle pour libérer le dit menu?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
            protected override void Dispose(bool disposing)
            {
                if (!disposed)
                {
                    if (disposing)                              // pour les objets disposables
                    {
                        if (menuInterne != null)                // libérer le menu
                            menuInterne.Dispose();
                    }
                    disposed = true;                            //un seul passage
                    base.Dispose(disposing);                    // appel du dispose de base
                }
            }
    Est-ce utile? Nuisible? Indifférent?
    Comment savoir ce que je dois libérer explicitement ou non?

    Question subsidiaire

    Si je crée une librairie de contrôle, et que je remplace la dérivation pour utiliser un contrôle existant (ex:TextBox) au lieu de UserControl, quel constructeur est le plus approprié,

    Celui-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            public MonControle()
            {
                InitializeComponent();
            }
    ou celui-là ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
           public MonControle() : base()
            {        }
    Et pourquoi?

    Merci d'avance
    Claude

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Février 2008
    Messages
    114
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 114
    Par défaut
    Bonjour,

    Je vais peut être dire une bêtise, mais pour ce qui est libération de ressource, si on se réfère à ce que dit microsoft avsec le "Dispose pattern", il faut libérer dans la méthode Dispose() (et bien sur implémenter IDisposable) les ressources, qui sont conservées lors de la durée de vie de ton objet. Donc je suppose que dans ton cas, tu devrais utiliser le code que tu montre.
    Par contre, plus généralement, il faut appeler Dispose sur tout les objets dont tu n'as plus utilité dés la fin de leur utilisation (si on ne veut pas avoir des surprises sur le nombre de handle qu'utilise ton application).

    Pour la question subsidiaire, je sais InitializeComponent est généré par l'éditeur visuel de VS et que si tu ne l'appel pas dans le constructeur par défaut, je doute que tu puisse utiliser ce dernier sans problèmes.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public MonControle() : base()
            {
                InitializeComponent();
            }
    me parait la meilleur solution.

  3. #3
    Membre très actif
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2008
    Messages : 612
    Par défaut
    Merci.

    Je précise le contexte.

    J'ai une série de contrôles dérivés de contrôles originaux.
    Avant, je me contentais de créer une classe "ordinaire" que je dérivais d'un contrôle. Donc, pas de designer, pas de classe.designer.cs etc, juste une unique classe moncontrol.cs : Control
    Je prenais en charge moi-même la libération comme indiqué.

    J'ai décidé de regrouper mes contrôles dans une solution, et de les transformer tous en bibliothèque de contrôles, afin de pouvoir les utiliser dans mes autres projets directement via la barre d'outils de VS (avant, il fallait recopier la classe dans le projet).

    Donc, maintenant que c'est une librairie de projets, la méthode onDispose est DEJA créée automatiquement dans le class.designer.cs, et donc évidemment je ne sais plus la surcharger une seconde fois dans mon contrôle.

    Est-ce que ce que la ligne :
    que le designer ajoute automatiquement effectue la libération des ressources de mon projet, ce qui rendrait inutile la libération explicite de chaque ressource utilisée?

    Et si non, où ajouter cette libération?

    Pour la question subsidiaire, je sais InitializeComponent est généré par l'éditeur visuel de VS et que si tu ne l'appel pas dans le constructeur par défaut, je doute que tu puisse utiliser ce dernier sans problèmes.
    En fait, cette question était aussi la conséquence du transfert de mes contrôles dérivés.

    A l'origine, avec ma façon de travailler, je n'avais évidemment pas d'initialisation automatique générée par le designer (pas de classe .designer.cs), et donc pas non plus de "InitialiseComponent".

    C'est pourquoi j'étais obligé d'appeler le constructeur de base du contrôle dans le constructeur de mon contrôle dérivé (seule méthode pour l'initialiser correctement).

    Avec la bibliothèque de contrôles, c'est différent.
    Mais en transférant un contrôle, j'ai oublié de modifier le constructeur, et je me suis aperçu que ça fonctionnait strictement de la même façon, d'où ma question sur les deux syntaxes.

    Merci
    Claude

  4. #4
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    la présence de fichier designer ou non n'est pas lié à une bibliothèque ou autre
    quand on hérite d'un control pour le modifier, pas de designer
    quand on fait un usercontrol il y a un designer

    dans les 2 cas (et dans toutes tes autres classes meme non graphiques) il faut disposer les objets disposables (connexions aux données aussi par exemple)

    pour un control, il faut overrides dispose(boolean) pour ajouter ses destructions puis appeler base.dispose(boolean)
    pour un usercontrol ou form, on peut modifier le dispose dans le fichier designer (ou s'abonner à l'évent Disposed)

    quelques infos ici :
    http://www.developpez.net/forums/d83...r/#post4810294

    mettre à null ne sert pas forcément, même pour les objets disposables

    il me semble aussi que quand un control (donc aussi un usercontrol et un form car ils héritent de control) est disposé, il dispose tous les controles enfants posés sur lui meme

    mais si à un moment on ne veut plus afficher un controle et qu'au lieu de mettre visible à false on le retire de son parent, alors il faudra le disposer soi meme


    pour ta question subsidiaire
    initializecomponent existe pour les usercontrol et form, il remplit l'interface
    il est obligatoire, et ce à chaque niveau
    si tu fais un UC qui hérite donc de usercontrol, ton uc va appeler le constructeur de base qui va appeler initializecomponent puis ta classe va appeler son initializecomponent
    (on peut dériver autant de fois qu'on veut, le comportement est le meme, chaque étage de la hiérrarchie ajoute ses controles)
    en vb.net intializecomponent est même implicite ainsi que le constructeur (on peut tout de même écrire le constructeur)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre très actif
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2008
    Messages : 612
    Par défaut
    pour un control, il faut overrides dispose(boolean) pour ajouter ses destructions puis appeler base.dispose(boolean)
    Oui, c'est ce que je faisais déjà, lorsque je dérivais directement de control et pas de usercontrol.

    pour un usercontrol ou form, on peut modifier le dispose dans le fichier designer (ou s'abonner à l'évent Disposed)
    Ok. Modifier dans le designer, je n'aime pas trop, parce que c'est sujet à erreur lorsqu'on recrée un projet du même genre en récupérant le code (oubli des modifs faites dans le designer).
    Donc, je retiens l'abonnement à Disposed.

    il me semble aussi que quand un control (donc aussi un usercontrol et un form car ils héritent de control) est disposé, il dispose tous les controles enfants posés sur lui meme
    Ben en fait, c'est un peu ma question exprimée différemment, c'est ce que je voulais savoir: J'ajoute un contrôle de type menu à mon contrôle dérivé (dans mon cas, un menu popup), est-ce que lorsque mon controle est disposé par le designer ça dispose automatiquement tous les contrôles fils qu'on a créé à l'intérieur, et donc mon menu, SANS devoir le faire explicitement?

    Vu que tu dis "il me semble", je reste un peu dans l'expectative.

    Merci, je faisais déjà un usage abondant de "using", mais ici c'était un contrôle fils qui reste global et détruit seulement à la destruction de son contrôle parent, et donc je ne peux ni l'inclure dans un using, ni le détruire autrement qu'en agissant au moment du dispose du contrôle parent.

    si tu fais un UC qui hérite donc de usercontrol, ton uc va appeler le constructeur de base qui va appeler initializecomponent puis ta classe va appeler son initializecomponent
    J'avais bien compris pour le contrôle dérivé de usercontrol. Je me suis probablement mal exprimé:

    Si je crée une classe directement dans mon projet, et que je dérive cette classe d'un controle (pas d'un usercontrol), genre

    classe MonTextBox : Texbox

    Je n'ai pas de designer et pas de initializecomponent, je crée mon constructeur avec appel au constructeur de la base (moncontrol() : base())
    et évidemment, ça fonctionne (sauf que je ne sais pas importer mon controle dans la barre d'outils d'un autre projet).

    Si par contre j'utilise le "wizard" de création d'un usercontrol, et qu'ensuite je remplace la dérivation de "usercontrol" en "control", pour revenir au cas précédent, j'ai bien un designer.cs et un initializecomponent.

    Mais que je remette mon constructeur avec appel au constructeur de "base" comme avant, ou que j'appelle initializecomponent SANS appeler le constructeur de base, ça semble fonctionner de façon identique (je n'ai pas de designer fonctionnel dans les deux cas, vu que j'ai modifié la classe de laquelle je dérive).

    Ma question était donc : Quelle est la différence entre les 2 syntaxes et laquelle est la mieux adaptée (pour un dérivé de control, pas de usercontrol où la question ne se pose pas).

    Bref, pour prendre un exemple élémentaire, ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
       public partial class MonTextBox : TextBox
       {
            public MonTextBox()                 // appel du constructeur de base
                : base()
            {}
        }
    ou ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
       public partial class MonTextBox : TextBox
       {
            public MonTextBox() 
            {
                 InitializeComponent();
            }
        }

    J'espère que j'ai été plus clair

    Merci
    Claude

  6. #6
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    voici un extrait du code de la méthode dispose de la classe control (trouvée via reflector)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     ControlCollection controls = (ControlCollection) this.Properties.GetObject(PropControlsCollection);
    if (controls != null)
    {
         for (int i = 0; i < controls.Count; i++)
         {
                Control control = controls[i];
                control.parent = null;
                control.Dispose();
         }
         this.Properties.SetObject(PropControlsCollection, null);
    }
    donc les controles enfants sont bien disposés

    pour qu'un control soit accessible dans la barre d'outils c'est comme pour un usercontrol

    faire un usercontrol, puis modifier en control c'est moche
    surtout si tu ne supprimes pas le fichier designer, étant donné que c'est un partial class les 2 fichiers sont mélangés à la compilation

    la méthode initializecomponent n'existe pas en cas d'héritage de control, donc ta question ne peut pas exister

    si les controles n'apparaissent pas automatiquement après compilation, faire clic droit ajouter des éléments ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Forcer la libération des ressources sur un fichier
    Par piotrr dans le forum Général Dotnet
    Réponses: 0
    Dernier message: 24/06/2009, 13h59
  2. libération des ressources (en scope=session)
    Par chmurb dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 20/02/2009, 14h16
  3. [Excel] Libération des ressources Excel+lenteur d'exectution
    Par zalalus dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 12/11/2007, 09h06
  4. Réponses: 2
    Dernier message: 29/09/2007, 13h56
  5. libération des ressource d'une table
    Par dracula2000 dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 07/06/2006, 18h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo