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

C# Discussion :

Destructeur toujours appellé ?


Sujet :

C#

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut Destructeur toujours appellé ?
    Bonjour, je voudrais savoir si dans certains cas le destructeur (dispose) n'était pas appeller alors même que l'objet serait supprimer de la mémoire ?

    Par exemple, si considérant un site en ASP.Net, j'ai dans ma session utilisateur un objet de classe X. Les dll du site, dont celles qui définissent la classe X sont mises à jour sur le serveur. Lorsque ma session devrait être lue, l'object de l'ancienne classe X n'est plus lisible (vu que la classe a "disparue" au profit d'une nouvelle version). Est-ce que dans ce cas par exemple, je suis certain que la méthode dispose (de la classe disparue) sera appellée ?

    Cela est essentiel pour faire certains cleanup DB.


    Merci aux 1000 premiers à répondre ainsi qu'au suivants.

  2. #2
    Membre confirmé Avatar de Redouane
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    435
    Détails du profil
    Informations personnelles :
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 435
    Points : 569
    Points
    569
    Par défaut
    Bonjour,

    Ce que je sais c'est que lorsqu'un objet abandonne la portée, il est libéré par le Common Language Runtime (CLR).
    il faut savoir que le GarbageCollector a pour but de libérer la mémoire des objets qui ne sont plus référencés dans le programme au cours de son exécution.

    Tu peux trouver ton besoin dans cet article de msdn :
    http://msdn.microsoft.com/fr-fr/library/hks5e2k6.aspx

    Je ne l'ai pas tt lu

    Cdt,

  3. #3
    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 : 42
    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
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    destructeur (dispose)
    Attention, le destructeur (ou Finalize) et la méthode Dispose sont 2 choses différentes ! Dispose sert, au départ, à libérer les ressources non-managées utilisées par un objet (même si par la suite on s'est rendu compte que ça pouvait servir à plein d'autres choses, notamment grâce à l'instruction using). Dispose n'est pas automatiquement appelé par le GC quand l'objet est collecté : il faut l'appeler explicitement dans le destructeur (méthode Finalize pour les langages qui n'ont pas de syntaxe pour le destructeur).

    Pour plus de détails et un exemple d'implémentation typique de IDisposable, va voir ce lien

    Citation Envoyé par Sergejack Voir le message
    Bonjour, je voudrais savoir si dans certains cas le destructeur (dispose) n'était pas appeller alors même que l'objet serait supprimer de la mémoire ?
    En cas de plantage "violent" (genre plantage du CLR, ce qui est assez rare), le destructeur ne sera pas appelé. Dans tous les autres cas, le GC se charge d'appeler automatiquement le destructeur sur les objets qui ne sont plus référencés. Par contre ça n'implique pas forcément un appel à Dispose, cf. ma remarque plus haut.

    Quand le process s'arrête, toute la mémoire qu'il utilisait est de toute façon libérée, que les destructeurs aient été appelés ou non.

    Citation Envoyé par Sergejack Voir le message
    Par exemple, si considérant un site en ASP.Net, j'ai dans ma session utilisateur un objet de classe X. Les dll du site, dont celles qui définissent la classe X sont mises à jour sur le serveur. Lorsque ma session devrait être lue, l'object de l'ancienne classe X n'est plus lisible (vu que la classe a "disparue" au profit d'une nouvelle version). Est-ce que dans ce cas par exemple, je suis certain que la méthode dispose (de la classe disparue) sera appellée ?

    Cela est essentiel pour faire certains cleanup DB.
    Je pense que ça dépend, entre autres, de comment tu gères tes sessions. Avec l'option par défaut (InProcess), les sessions sont conservées en mémoire, il n'y a donc pas besoin de sérialisation. Si tu utilises un autre mode de stockage des sessions (base de données, fichiers...), effectivement ça peut sans doute poser un problème...

    Quand tu remplaces tes assemblies par une version plus récente, ça provoque le redémarrage de l'application, mais avant le redémarrage la version actuelle de l'assembly est encore en mémoire : tu peux donc sans doute exécuter du code pour gérer proprement l'arrêt de l'application (dans les évènements Application_End et Session_End par exemple)

  4. #4
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    En C# les destructeurs sont toujours appelés. La seule inconnue, c'est de savoir à quel moment ils le seront. Après, il y a plusieurs manières :
    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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     
    class X
    { 
       ...
       ~X()
       {
          //toujours appelé
       }
    }
     
    class X : IDisposable
    { 
       ...
       ~X()
       {
          //toujours appelé
       }
     
       public void Dispose()
       {
          //appelé s'il y a un appel explicite à Dispose ou que l'instance de X est utilisée via un using(){}
       }
    }
     
    class X : IDisposable
    { 
       ...
       ~X()
       {
          //toujours appelé
          Dispose(false);
       }
     
       bool disposed = false;
     
       private void Dispose(bool disposing)
       {
          //toujours appelé au minimum 1 fois (peut être appelé plusieurs fois)
          if(!this.disposed)
          {
              disposed = true;
              //grâce à la condition, on ne passe ici qu'une fois dans la vie de l'objet
     
              if(disposing)
              {
                 //appelé lors d'un appel explicite à Dispose ou un blog using(){}
              }
              else
              {
                 //appelé lorsque l'objet meurt via le destructeur ~X()
              }
          }
       }
     
       public void Dispose()
       {
          //appelé s'il y a un appel explicite à Dispose ou que l'instance de X est utilisée via un using(){}
          Dispose(true);
       }
    }

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 175
    Points : 25 116
    Points
    25 116
    Par défaut
    en résumé

    pour les classes du framework, aucune question à se poser, on peut appeler dispose, et dispose sera forcément appelé si on ne l'a pas fait car finalize l'appelera

    tant qu'on écrit des classes .net, aucune question à se poser, il ne sert à rien d'implémenter IDisposable

    après si tu écris des choses non managées il faut bien lire le pattern de IDisposable avec overrides du finalize

    (on est encore loin des 1000 mais y a de la pointure)

  6. #6
    Expert éminent
    Avatar de StormimOn
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2005
    Messages
    2 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Sarthe (Pays de la Loire)

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

    Informations forums :
    Inscription : Mai 2005
    Messages : 2 593
    Points : 7 660
    Points
    7 660
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    pour les classes du framework, aucune question à se poser, on peut appeler dispose, et dispose sera forcément appelé si on ne l'a pas fait car finalize l'appelera
    Sauf qu'il y a une question à se poser : la classe possède-t-elle une méthode Dispose ? Si oui il faut libérer explicitement lorsque l'objet n'est plus utile (appel de la méthode Dispose) afin d'aider le GC à faire son travail correctement. J'ai déjà vu des problèmes parce que la personne n'appelait pas les Dispose en se disant que de toute façon le GC se chargera de gérer tout ça.

    Je pense que c'est une règle qu'il faut appliquer, sans se poser de question cette fois. Le premier réflexe à avoir c'est de regarder si une méthode Dispose existe lorsque l'on ne connait pas la classe que l'on utilise (généralement il y aura une méthode Close aussi, les deux donnant le même résultat). Ensuite le second réflexe c'est d'appeler Dispose dès lors que l'objet n'est plus utile.

    Citation Envoyé par sperot51 Voir le message
    tant qu'on écrit des classes .net, aucune question à se poser, il ne sert à rien d'implémenter IDisposable
    Je dis non car on peut écrire des classes .Net qui possèdent des membres implémentant IDisposable (un Stream ou une collection d'images par exemple) et à ce moment il faut implémenter IDisposable.

  7. #7
    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 : 42
    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
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    pour les classes du framework, aucune question à se poser, on peut appeler dispose, et dispose sera forcément appelé si on ne l'a pas fait car finalize l'appelera
    Il vaut mieux appeler quand-même Dispose explicitement : si on ne le fait pas, effectivement ce sera finalement appelé par le destructeur, sauf qu'on ne sait pas quand le destructeur sera appelé : il n'y a pas moyen de prévoir quand le GC va collecter l'objet, ça peut aussi bien être dans 30 secondes que dans 10h. Si l'objet est couteux en RAM, utilise des ressources système ou bloque l'accès à un fichier, tu as tout intérêt à faire un Dispose dessus le plus tôt possible...

    Citation Envoyé par sperot51 Voir le message
    tant qu'on écrit des classes .net, aucune question à se poser, il ne sert à rien d'implémenter IDisposable
    Bien sûr que si ! En fait, la règle que j'essaie d'appliquer est la suivante : dès qu'une de mes classes a des champs dont le type implémente IDisposable, j'implémente aussi IDisposable pour libérer ces objets.
    Il y a aussi d'autres cas d'utilisation de IDisposable, par exemple pour créer un "scope" avec un block using. Cela permet de s'assurer que le code de "nettoyage" du scope est bien efffectué à la fin du block using

  8. #8
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Ok, ok.

    Il me faudrait encore la confirmation d'une chose, la méthode Dispose n'a pas à supprimer toutes les ressources managées de l'instance (Le faire serait mieux mais ne pas le faire n'aurait pas de conséquence grave) ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public void Dispose(bool disposing)
    {
    	/* Je m'en fiche, je commente tout !
    	if (disposing)
    	{
    		[...]
    	}
    	*/
    	// gestion des ressources non managées
    	[...]
    }
    Et dans la gestion des ressources non managées, je peux très bien excécuter un query qui supprime des enregistrements dans une table ?

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 175
    Points : 25 116
    Points
    25 116
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Ok, ok.

    Il me faudrait encore la confirmation d'une chose, la méthode Dispose n'a pas à supprimer toutes les ressources managées de l'instance (Le faire serait mieux mais ne pas le faire n'aurait pas de conséquence grave) ?
    un system.Drawing.image est une ressources non managées, ce n'est pas écrit en .net, c'est windows via les dll gdi qui s'occupent d'allouer la mémoire et de faire le traitement dessus
    quand on appelle dispose sur une image, ca appelle dans la dll gdi la fonction qui supprime l'image de la mémoire

    par contre pour une classe écrite en .net (par exemple une personne avec un nom as string, un prénom, une date de naissance etc...)
    ca se passe de la manière suivante
    tu fais un new pour avoir une instance, cette instance prend de l'espace en mémoire, en placant cette instance dans une variable, tu as un pointeur sur cet espace mémoire
    tu peux mettre cette variable à null, mais l'espace est encore présent
    c'est le garbage collector qui s'occupera de vider l'espace mémoire, il verra que plus personne n'utilise cet espace mémoire
    implémenter dispose sur cette classe "personne" ne sert strictement à rien !

    il est possible d'avoir plusieurs variables qui pointent vers la meme instance
    quand il n'y a plus aucune référence vers une instance, tous les membres de cette instance sont mis à null eux aussi s'ils ne sont pas référencés par d'autres (j'abrège mais c'est à peu près ca)
    donc meme si dans une classe personne tu as la photo as system.drawing.image, et que tu n'implémentes pas dispose dessus, y aura pas de soucis, dès que plus personne ne référencera l'image, la méthode finalize sera appelée, et elle appelera Dispose sur l'image, libérant ainsi la mémoire prise par l'image

  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 : 42
    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
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Et dans la gestion des ressources non managées, je peux très bien excécuter un query qui supprime des enregistrements dans une table ?
    Tu peux... mais bon, ça me parait quand même pas très solide comme design
    (à moins que tu appelles Dispose explicitement). Si tu attends que le GC collecte l'objet, tu n'as aucune idée de quand Dispose sera exécuté...

  11. #11
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    Surtout, surtout, ne jamais accéder à un objet managé qui n'est référencé nul part ailleurs un finalizer ou dans un Dispose appelé par le finalizer. C'est une règle.

    En fait le GC fonctionne avec des graphs d'objets construits en fonction des référence.
    Donc tu as un objet A qui est référencé par un objet B et C utilisé dans ton application. Si tu libères les références vers B et C alors lorsque le GC va passer il aura un graphe contenant les objets A, B et C. Et c'est tout ce qui est prévisible, l'ordre dans lequel les finalizers seront appelés sur A, B et C n'est pas prévisible (en général c'est linéaire mais il ne faut pas prendre cela pour une généralité).

    Donc en terme de GC il se peut très bien qu'en essayant d'accéder à un objet managé dans un finalizer il se peut très bien que cet objet ai lui même déjà finalisé et donc les finalizers pourraient avoir un NullReferenceException, ObjectDisposedException ou autres bizarreries de ce genre.

  12. #12
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Citation Envoyé par smyley Voir le message
    Surtout, surtout, ne jamais accéder à un objet managé qui n'est référencé nul part ailleurs un finalizer ou dans un Dispose appelé par le finalizer. C'est une règle.

    En fait le GC fonctionne avec des graphs d'objets construits en fonction des référence.
    Donc tu as un objet A qui est référencé par un objet B et C utilisé dans ton application. Si tu libères les références vers B et C alors lorsque le GC va passer il aura un graphe contenant les objets A, B et C. Et c'est tout ce qui est prévisible, l'ordre dans lequel les finalizers seront appelés sur A, B et C n'est pas prévisible (en général c'est linéaire mais il ne faut pas prendre cela pour une généralité).

    Donc en terme de GC il se peut très bien qu'en essayant d'accéder à un objet managé dans un finalizer il se peut très bien que cet objet ai lui même déjà finalisé et donc les finalizers pourraient avoir un NullReferenceException, ObjectDisposedException ou autres bizarreries de ce genre.
    Je n'ai vraiment pas compris ce que tu disais.

    Si j'ai une instance de N qui possède un champs privé dispoable M connu de N seul (cette instance de M n'est donc accessible par cette instance de N), je ne dois pas surtout pas appellé Dispose sur M dans le finalizer de N ??

  13. #13
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    aie aie

    En clair, une fois qu'une série d'objets n'est plus accessibles par ton application le GC les dispose, mais il n'y a pas d'ordre dans se processus. Microsoft préviens même qu'à l'avenir il se pourrai que les finalizers soient exécutés par plusieurs threads à la fois. Donc pas grand chose garantit que dans un finalizer l'objet managé auquel tu accèdes ai déjà eu son finalizer appelé ou non.

  14. #14
    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 : 42
    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
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par smyley Voir le message
    Surtout, surtout, ne jamais accéder à un objet managé qui n'est référencé nul part ailleurs un finalizer ou dans un Dispose appelé par le finalizer.
    il manque pas un bout dans ta phrase ?

  15. #15
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Citation Envoyé par smyley Voir le message
    aie aie

    En clair, une fois qu'une série d'objets n'est plus accessibles par ton application le GC les dispose, mais il n'y a pas d'ordre dans se processus. Microsoft préviens même qu'à l'avenir il se pourrai que les finalizers soient exécutés par plusieurs threads à la fois. Donc pas grand chose garantit que dans un finalizer l'objet managé auquel tu accèdes ai déjà eu son finalizer appelé ou non.
    Est-ce que cela veut dire (qu'à l'exception des types des bases ?) je dois considérer tous mes objets comme détruits dans Dispose ?

    Parce qu'alors je ne vois pas ce qu'on peut bien faire au sujet des resources managées (il est indiqué dans les best practice que c'est là qu'il convient de s'en charger).

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 175
    Points : 25 116
    Points
    25 116
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Si j'ai une instance de N qui possède un champs privé dispoable M connu de N seul (cette instance de M n'est donc accessible par cette instance de N), je ne dois pas surtout pas appellé Dispose sur M dans le finalizer de N ??
    en repartant de cet exemple, la classe N a une variable privée M
    dans le dispose de N il ne faut pas accéder à M, car il a pu etre détruit avant !

  17. #17
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    heu ... ?
    Surtout, surtout, ne jamais accéder à un objet managé qui n'est référencé nul part ailleurs dans un finalizer, ou dans un Dispose appelé par le finalizer.

  18. #18
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Est-ce que cela veut dire (qu'à l'exception des types des bases ?) je dois considérer tous mes objets comme détruits dans Dispose ?

    Parce qu'alors je ne vois pas ce qu'on peut bien faire au sujet des resources managées (il est indiqué dans les best practice que c'est là qu'il convient de s'en charger).
    C'est pour ça que le Dispose il est double en fait :
    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
     
       private void Dispose(bool disposing)
       {
          if(!this.disposed)
          {
              disposed = true;
     
              if(disposing)
              {
                 //ici il est utile de parfois libérer soit même les objets managés utilisé car c'est un appel manuel de Dispose (via un bloc using ou autre) et pas par le GC. Le graphe d'objet est donc encore intacte et tu peux y faire absolument tout ce que tu veux
              }
              else
              {
                 //Ici c'est le GC qui a appelé la fonction et donc bien qu'en général on peut accéder à certains objets managés de la classe, il faut éviter de le faire car ce n'est pas une valeur sûre. Le GC ne garantit aucunement que le Dispose des objets managés présents dans la classe n'a pas été déjà appelé. Si par exemple on a un Stream dans la classe et qu'on y accède on pourrai tomber à l'improviste sur un ObjectDisposedException sans vraiment savoir d'où ça vient
              }
          }
       }

  19. #19
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    Je vois.

    Par ailleurs, apparement dans le finalize on ne peut pas créer de SqlConnection sous risque d'avoir une erreur avec le handler (Handle is not initialized) parce que pooling.
    Ce qui me met dans l'ambarras vu que mon but est de supprimer des records de la DB à la mort de l'objet.

    Donc, je ne peux faire qu'une seule chose, imposer (à moi et ... y a que moi, là mais bon...) l'emploie du dispose préalable à toute perte de la dernière référence.



    Pas très pertinent l'existance d'une déclaration d'un destructeur dans pareille circonstances.

  20. #20
    Expert éminent
    Avatar de smyley
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    6 270
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 6 270
    Points : 8 344
    Points
    8 344
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    Ce qui me met dans l'ambarras vu que mon but est de supprimer des records de la DB à la mort de l'objet.
    Ce n'est peut être pas recommandé mais pour ma propre db ou j'avais besoin de faire des choses similaires j'ai pensé à réutiliser un truc (fou ).

    En fait il est possible de réutiliser l'idée du RefCount utilisé dans COM pour libérer les objets. Quand on fait la première demande à une ressource, on crée l'objet de données, et on le met dans une liste (List<T>) de toutes les ressources actuellement allouée afin d'y garder une référence. Elle a une propriété RefCount qui vaut initialement 0. Ensuite, on renvois au demandeur un objet qui lui va être une classe à part donnant accès au données de la ressources. Dans le constructeur de cette classe on augmente le refcount de la ressource et dans le finalizer on le décrémente. Ainsi, lorsque le refcount repasse à 0 on appelle dispose sur la ressource avant de la supprimer de la liste, et vu que la le Dispose est appel manuellement alors on est sur que la ressource n'a pas déjà été disposé et qu'elle est donc toujours valide.

    Après les problèmes qu'il reste sont des problèmes de synchronisations à réglé (car le finalizer n'est pas appelé dans le même thread que le reste de l'application) mais et ce n'est peut être pas adapté à ta situation, mais c'est une idée

Discussions similaires

  1. Réponses: 9
    Dernier message: 30/11/2007, 11h15
  2. Réponses: 2
    Dernier message: 12/07/2007, 10h12
  3. destructeur pas appelé ?
    Par NiamorH dans le forum C++
    Réponses: 28
    Dernier message: 27/04/2007, 16h20
  4. Réponses: 9
    Dernier message: 07/10/2006, 10h54
  5. [destructeur] [pas appelé]
    Par Gonath dans le forum C++
    Réponses: 11
    Dernier message: 23/02/2006, 18h37

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