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

VB.NET Discussion :

Evenement avant la destruction d'une classe


Sujet :

VB.NET

  1. #1
    gph
    gph est déconnecté
    Membre confirmé Avatar de gph
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2005
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 99
    Par défaut Evenement avant la destruction d'une classe
    Bonjour,

    Je me heurte à un problème que je n'arrive pas à résoudre avec mon niveau de compétence et je viens donc chercher des pistes ici.

    Le contexte :
    J'ai une classe VB.NET qui utilise une voie série pour communiquer avec un appareil embarqué.

    Le problème :
    Lors de la destruction de la classe, il me faut envoyer une commande de mise en veille sur la voie série.
    Hors, lorsque j'ai mon event Finalize, les ressources sont déjà libérées donc mon objet SerialPort n'est plus disponible.

    Y a t il un moyen (de manière autonome à la classe) d'obtenir un event (ou un overload) du type before_close ?

    Merci.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Est-ce que ta classe implémente IDisposable ?

  3. #3
    gph
    gph est déconnecté
    Membre confirmé Avatar de gph
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2005
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 99
    Par défaut
    Non.

    J'ai exploré cette piste, mais Dispose n'est pas appelé automatiquement (enfin si j'ai compris)

  4. #4
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par défaut
    Citation Envoyé par gph Voir le message
    Non.

    J'ai exploré cette piste, mais Dispose n'est pas appelé automatiquement (enfin si j'ai compris)

    Si. Dispose est appelé quand l'objet est ... "disposed". En revanche, si tu n'utilises pas de "using" (je ne connais pas l'équibalent VB.Net) tu ne peux pas avoir quand il sera appelé.

  5. #5
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2010
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 291
    Par défaut
    Bonjour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Using
    ....
    End using
    Existe aussi en VB.Net

    Pour ma part dans un cas similaire j'implémente une fonction Liberer() dans ma classe et je place le code que je veux avant d'appeler MyBase.Finalize:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     Public Sub liberer()
            '.... Le code qui nettoie ou pour vous qui met en veille
            MyBase.Finalize()
        End Sub
    Puis dans le code qui utilise la classe j'appelle cette fonction avant la destruction de l'objet que je force par un GC.collect()

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Geo2A Voir le message
    Pour ma part dans un cas similaire j'implémente une fonction Liberer() dans ma classe et je place le code que je veux avant d'appeler MyBase.Finalize:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     Public Sub liberer()
            '.... Le code qui nettoie ou pour vous qui met en veille
            MyBase.Finalize()
        End Sub
    Puis dans le code qui utilise la classe j'appelle cette fonction avant la destruction de l'objet que je force par un GC.collect()
    Ca ne sert à rien d'appeler Finalize, c'est le GC qui s'en charge. D'ailleurs, l'implémentation par défaut de Finalize ne fait strictement rien, et la plupart des classes ne la redéfinissent pas (sauf, notamment, celles qui implémentent IDisposable).

    D'autre part, appeler explicitement GC.Collect n'est absolument pas recommandé. C'est un traitement lourd et donc pénalisant pour les performances. Le CLR se charge de déclencher la collecte quand c'est nécessaire, ça ne sert à rien de le faire soi-même

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2010
    Messages
    291
    Détails du profil
    Informations personnelles :
    Âge : 57
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 291
    Par défaut
    Bonsoir,

    Les indications de Tomlev pourrons peut-être m'éclaircir sur un point, car j'ai actuellement un gros pb relatif au garbage collector. J'utilise une DLL en C pour lire et gérer des images, cette dll est wrappé pour le .NET (par mes soins), si je laisse le GC faire son boulot tout seul très rapidement le système manque de mémoire (pourtant il y a 4 Go de RAM), si j'utilise ma méthode j'arrive à faire fonctionner le truc (plus un GC.addmemorypressure et le release qui va avec), mais au bout d'un moment il n'y a plus d'affichage de l'image à l'écran et la seule façon de faire est le reboot du PC, il y a donc des fuites quelque part ...

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    @gph, Dispose n'est jamais appelé automatiquement (sauf cas du bloc Using), c'est à toi de le faire. Et c'est dans cette méthode qu'il faut libérer le port série. Tu peux également overrider Finalize, et appeler Dispose à partir de là. De cette façon, quand le GC collectera ton objet, il appelera Finalize, qui appelera Dispose. Ca permet de s'assurer que la ressource sera libérée au final, même si tu n'as pas appelé DIspose explicitement.

    L'implémentation typique ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
     
    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            ' Dispose managed resources
            ' ...
        End If
     
        ' Dispose unmanaged resources
        ' ...
     
    End Sub
     
    Protected Overrides Sub Finalize()
        Dispose(False)
    End Sub
    (pour un exemple plus détaillé regarde la doc de l'interface IDisposable)

    Citation Envoyé par Geo2A Voir le message
    Les indications de Tomlev pourrons peut-être m'éclaircir sur un point, car j'ai actuellement un gros pb relatif au garbage collector. J'utilise une DLL en C pour lire et gérer des images, cette dll est wrappé pour le .NET (par mes soins), si je laisse le GC faire son boulot tout seul très rapidement le système manque de mémoire (pourtant il y a 4 Go de RAM), si j'utilise ma méthode j'arrive à faire fonctionner le truc (plus un GC.addmemorypressure et le release qui va avec), mais au bout d'un moment il n'y a plus d'affichage de l'image à l'écran et la seule façon de faire est le reboot du PC, il y a donc des fuites quelque part ...
    Là comme ça je vois pas trop, ça dépend de comment tu as implémenté ton wrapper... De toutes façons, pose plutôt ta question dans une nouvelle discussion stp, histoire de pas squatter la question de gph

  9. #9
    gph
    gph est déconnecté
    Membre confirmé Avatar de gph
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2005
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 99
    Par défaut
    Merci pour vos réponses qui m'éclairent mais ne résolvent pas mon problème tel que je le souhaite.

    Merci pour la méhtode du disposable que j'avais essayé mais avec des erreurs de ma part.

    En fait ce n'est pas libérer les ressources que je veux puisque ce n'est que du code managé, mais effecuter une action avant la libération.
    Hors le finalize arrive trop tard et je n'ai pas d'évènement antérieur.

    Il faut que j'implémenteune méthode de fermeture qui sera appelée par l'objet ayant instancié la classe et c'est ça que je voulais éviter.
    Je voulais que ça soit automatique.

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par gph Voir le message
    En fait ce n'est pas libérer les ressources que je veux puisque ce n'est que du code managé
    Un port série est une ressource non managée...

  11. #11
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par défaut
    Bonjour

    Citation Envoyé par gph Voir le message
    Il faut que j'implémenteune méthode de fermeture qui sera appelée par l'objet ayant instancié la classe et c'est ça que je voulais éviter.
    Je voulais que ça soit automatique.
    La réponse a pourtant été donné , on va la redécrire :

    - implementer ce code de finalisation dans la méthode Dispose (donc implémenter IDisposable).

    - instancier la classe dans un bloc Using : ainsi la méthode Dispose sera appelé lors de la sortie du bloc, et le code de finalisation appelé de manière deterministe à ce moment..

    Je ne vois pas en quoi cela ne répond pas à ta problématique.

  12. #12
    gph
    gph est déconnecté
    Membre confirmé Avatar de gph
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2005
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 99
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Un port série est une ressource non managée...
    Heu ...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Class ...
    Protected Friend WithEvents ComDevice As SerialPort
     
    Public Sub New()
    ComDevice = New IO.Ports.SerialPort
    ...
    Le MSDN indique que la méthode Dispose existe, je n'ai donc pas à libérér la ressource, non ?
    C'est peut être mon terme "Managé" qui n'était pas adapté ?


    Je viens de refaire des essais.
    La méthode Dispose s'implémente en effet, elle est appelé lors du FInalize, hors c'est trop tard.
    Car a cet endroit le SerialPort est déjà fermé je ne peux donc plus communiquer !

    Je reformule mon besoin :
    Est il possible d'avoir un évènement annonçant la prochaine fermeture de la classe à l'intérieur de celle-ci ? (Style form_queryunload en VB6 mais pour une classe .NET)


    NB : Le Using n'existe pas en VB.NET

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par gph Voir le message
    Le MSDN indique que la méthode Dispose existe, je n'ai donc pas à libérér la ressource, non ?
    Dispose sert à libérer explicitement (et donc de façon déterministe) une ressource. C'est à toi de l'appeler (soit explicitement soit avec un bloc Using), ce ne sera pas fait automatiquement.

    Citation Envoyé par gph Voir le message
    C'est peut être mon terme "Managé" qui n'était pas adapté ?
    Managé, ça veut dire géré par le garbage collector. Donc en gros ça concerne exclusivement la mémoire utilisée par le code .NET. Tout le reste (mémoire utilisée par du code natif, handles de fichiers ou de ports série, etc) n'est pas managé. Même s'il existe des classes pour wrapper ces ressources (FileStream, SerialPort...), il faut quand même les libérer. Si tu ne le fais pas, le garbage collector finira par le faire (s'il n'y a plus de référence à ces objets), mais il est impossible de prévoir quand... peut-être dans 5 secondes, peut-être dans 3 jours !

    Citation Envoyé par gph Voir le message
    La méthode Dispose s'implémente en effet, elle est appelé lors du FInalize, hors c'est trop tard.
    Car a cet endroit le SerialPort est déjà fermé je ne peux donc plus communiquer !
    Encore un fois : c'est à toi d'appeler Dispose, et de faire ce que tu veux faire avant.

    Citation Envoyé par gph Voir le message
    Je reformule mon besoin :
    Est il possible d'avoir un évènement annonçant la prochaine fermeture de la classe à l'intérieur de celle-ci ? (Style form_queryunload en VB6 mais pour une classe .NET)
    Non. D'ailleurs la "fermeture d'une classe", ça ne veut rien dire...
    En fait je ne comprends pas trop ton besoin : tu ne sais pas à quel moment tu fermes le port ?

    Citation Envoyé par gph Voir le message
    NB : Le Using n'existe pas en VB.NET
    Ah bon ?
    http://msdn.microsoft.com/fr-fr/library/htd05whh.aspx

    A moins que tu utilises une très ancienne version, ça existe... je pense que c'est là au moins depuis VB2005.

    EDIT: effectivement ça n'existait pas en VB2003...

  14. #14
    gph
    gph est déconnecté
    Membre confirmé Avatar de gph
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2005
    Messages
    99
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2005
    Messages : 99
    Par défaut
    Meric pour les éclaircissements, je vais finir par comprendre un certains nombre de choses

    Citation Envoyé par tomlev Voir le message
    D'ailleurs la "fermeture d'une classe", ça ne veut rien dire...
    Quand la dernière instance ne l'utilise plus.

    Citation Envoyé par tomlev Voir le message
    En fait je ne comprends pas trop ton besoin : tu ne sais pas à quel moment tu fermes le port ?
    Il y a une classe qui est instanciée par une forme.
    Cette (ma) classe utilise une voie série.
    Lorsque la forme se ferme ou lorsqu'elle libère l'instance, je voudrais (sans implémenter une action spécifique dans la forme) utiliser la voie série et la fermer.
    Ce n'est pas moi qui écrit l'utilisation de ma classe, je voudrais donc prévenir une mauvaise utilisation.

    Hors lorsque j'utilise Finalize, qui est bien appelé lors de la destruction de ma classe, la voie série est déjà fermée !
    Je ne peux donc pas l'utiliser.
    C'est visiblement le CLR qui la ferme avant que j'ai la main.

    Un risque est aussi une exception non gérée dans la Forme appelante qui va laisser l'appareil connecté à la voie série dans un état bancal.


    Est ce plus clair ?


    Pour le Using, en effet ça existe et je ne connaissais pas pour VB.

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par gph Voir le message
    Ce n'est pas moi qui écrit l'utilisation de ma classe, je voudrais donc prévenir une mauvaise utilisation.
    OK... déjà, il faut bien voir que tu ne pourras jamais prévenir complètement une mauvaise utilisation.

    Par contre, tu peux encourager une bonne utilisation. Par exemple, le fait d'implémenter IDisposable donne une indication à celui qui utilise ta classe : les bonnes pratiques recommandent de toujours appeler Dispose à la fin de l'utilisation d'un objet IDisposable. Donc ce sera à lui d'appeler Dispose sur ta classe, par exemple lors de la fermeture de la fenêtre. Et toi, dans ta méthode Dispose, tu mets le code dont tu as besoin, et tu Dispose explicitement le SerialPort...

    Je pense que c'est la façon la plus propre de faire, mais peut-être que quelqu'un a d'autres suggestions...

  16. #16
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Par défaut
    Citation Envoyé par tomlev Voir le message
    OK... déjà, il faut bien voir que tu ne pourras jamais prévenir complètement une mauvaise utilisation....
    Le foolproofing c'est une des versions IT de la quête du graal : un parcours initiatique sans fin

Discussions similaires

  1. Destruction d'une classe sous PHP5
    Par ctrl+z dans le forum Langage
    Réponses: 8
    Dernier message: 12/01/2009, 10h32
  2. Evenement dans une classe
    Par charliejo dans le forum Flash
    Réponses: 8
    Dernier message: 08/01/2007, 15h28
  3. Plantage lors de la destruction d'une classe
    Par xwindoo dans le forum C++
    Réponses: 10
    Dernier message: 04/10/2006, 17h01
  4. Réponses: 4
    Dernier message: 23/04/2006, 11h36
  5. destruction d'une classe qui herite de CDialog
    Par philippe V dans le forum MFC
    Réponses: 2
    Dernier message: 03/02/2004, 18h39

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