Classe de fichiers Log : utilisation d'un destructeur.
Picsonald
Messages postés23Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention 7 novembre 2020
-
18 févr. 2009 à 15:44
Picsonald
Messages postés23Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention 7 novembre 2020
-
23 févr. 2009 à 22:05
Bonjour à tous,
Actuellement, je me développe une classe qui va me permettre d'éditer des fichiers Logs. Pour plus de clarté, j'ai choisi d'écrire ces fichiers logs en html. Par conséquent, chacun d'eux commence par un "<html>" et se termine par un "
</html>".
Ne voulant pas faire appel à une méthode qui vient clôturer le log à la fin de l'éxécution du programme, j'aimerais qu'un destructeur se charge de fermer le log.
Je suis parvenu a le faire, mais voilà, dans mon destructeur, souvent, le flux d'écriture a été déjà fermé, et certains objets ne sont plus instanciés. Donc je les remets d'applomb en vitesse, pour écrire les dernières lignes.
Je suis convaincu que ma solution n'est pas la bonne : C'est une bidouille. De plus, lorsque mon programme est brutalement arrété, mon log ne se cloture pas...
cs_casy
Messages postés7741Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention24 septembre 201440 18 févr. 2009 à 20:38
J'ai effectivement fait ce même code (en vb mais c'est pas important) pour une classe log aussi.
J'ai mis le code dans la sub FinaLize et je n'ai jamais rencontrer ce problème, ma dernière ligne est bien écrite dans le fichier, même lors d'un arret brutal du logiciel.
Par contre, j'utilise System.IO.File.AppendAllText pour écrire dans le fichier, ce qui fait que je n'ai pas d'instance d'objet à conserver, et donc à détruire dans le destructeur, en contre partie, le fichier est automatiquement ouvert et refermé à chaque écriture.
Picsonald
Messages postés23Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention 7 novembre 2020 18 févr. 2009 à 22:42
Merci pour ta réponse, c'est très gentil.
J'ai beaucoup de mal a distinguer la méthode Finalize et le destructeur (avec le signe ~ devant). En fait, on ne m'a pas exposé ces notions lors de mes cours de programmation orientée objet... Je ne parviens donc pas a me servir de la méthode Finalize en C#.
Je regarderais un peu plus en détail cet "AppendAlltext", mais je dois reconnaitre que je ne veux pas que ma classe Log ralentisse exécivement mon programme. Ma classe est conçue de telle manière a garder le fichier ouvert pendant un certain temps, après quoi il se referme automatiquement, et se tient prêt a être rouvert.
Celà permet de ne pas faire de multiples ouvertures/fermetures de fichier, et permet de laisser le fichier disponible à la lecture si besoin, pendant que le programme est en route. Cependant, pour que tout soit bien marqué dans mon fichier, je fais appel à la méthode Flush qui force l'écriture à l'instant t. Je me demande si ceci ne présente pas une grosse perte de perfomances...
Celà dit, le plus gros problème que j'ai actuellement c'est cette histoire de destructeur...
RougailSaucisse
Messages postés118Date d'inscriptionlundi 16 février 2009StatutMembreDernière intervention 6 décembre 20101 18 févr. 2009 à 23:58
Salut,
Pour gérer la libération de ressources tu as 2 choses: Finalize et Dispose.
Finalize sera appelée par le GC (le rammasse-miette). Le problème étant que tu ne peux savoir quand sera effectivement appelée ta méthode finalize car elle est justement gérée par le GC et non par toi.
Si tu veux controler le moment ou tu libères tes resources, il faut que ta classe implemente l'interface IDisposable. Ainsi tu libéreras tes objets en faisant un appel explicite à TonObjet.Dispose(), ou encore en utilisant un "using"
using(MyClass mc = new MyClass())
{
}
Dès lors que "sortira" des parenthèses, la méthode Dispose de ta class MyClass sera appelée automatique. Donc soit tu appelles dispose explicitement soit tu utilises cette notation au choix.
Pour info lorsque tu utilises un destructeur:
~MyClass
{
}
cela revient exactement à faire un
protected override Finalize() { ...}
Dans les 2 cas, (~ ou Finalize) c'est le GC qui est chargé d'appeler ta méthode.
Picsonald
Messages postés23Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention 7 novembre 2020 19 févr. 2009 à 09:55
Merci pour tes explications.
Je vais faire des essais pour voir si la méthode Dispose est appelée même ne cas de fermeture brutale du programme (= kill du processus).
Est-ce que tu sais pourquoi dans mon destructeur, mes flux de fichiers sont déjà fermés, et certains de mes objets ne sont plus instanciés comme ils devraient l'être ?
Merci,
Pics'
Vous n’avez pas trouvé la réponse que vous recherchez ?
krimog
Messages postés1860Date d'inscriptionlundi 28 novembre 2005StatutMembreDernière intervention14 février 201549 19 févr. 2009 à 09:56
Salut
Effectivement, Finalize n'est pas le plus efficace, car le GC ne fonctionne pas comme en Java. En .net, s'il reste de la place mémoire et par soucis d'efficacité, ton programme ne se gênera pas pour l'utiliser et ne perdra pas de temps à vider la mémoire.
C'est seulement au moment où il n'y a plus assez d'espace mémoire que ton GC efface les objets non référencés, et c'est donc uniquement à ce moment que Finalize est appelé (il est toujours possible d'appeler manuellement le GC par un GC.Collect() si ma mémoire est bonne).
Picsonald
Messages postés23Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention 7 novembre 2020 19 févr. 2009 à 17:18
Oui, j'avais remarqué ce comportement. Merci pour ces informations.
Cela dit, dans mon cas, mon objet de Log reste instancié du début à la fin du programme.
La solution proposée par RougailSaucisse (utiliser l'instruction "using") fonctionne bien. Ma méthode "Dispose()" est appelée toute seule en fin de programme (oui, mon "using" se situe dans le main de mon "Program.cs" ^^).
Le truc que je ne parviens pas a faire, c'est éxécuter cette méthode "Dispose()" même lorsque le programme s'arrête brutalement (exemple : kill du processus)... En effet, un "using" ne suffit pas. J'ai arpenté le web, mais n'ai rien trouvé qui semble répondre à ce problème...
RougailSaucisse
Messages postés118Date d'inscriptionlundi 16 février 2009StatutMembreDernière intervention 6 décembre 20101 20 févr. 2009 à 05:12
Désolé, je ne pourrai pas te repondre conernant le fait de log même lorsque le programme plante. Cependant je peux te conseille de ne pas faire d'appel explicite a GC.Collect() ^^
krimog
Messages postés1860Date d'inscriptionlundi 28 novembre 2005StatutMembreDernière intervention14 février 201549 20 févr. 2009 à 10:53
D'un autre côté, c'est vrai qu'avec un kill du processus, il s'arrête tout de suite, il ne s'amuse pas à continuer les méthodes dans sa pile.
Je penserais alors plutôt à un 2eme programme indépendant que tu lances en parallèle, qui se chargera uniquement du log. Ainsi, si ton programme principal plante ou est kill, ton log continuera quand même.
Cependant, je ne sais pas comment faire communiquer 2 applications entre elles, mais je suis sûr qu'on peut facilement trouver des informations à ce propos. (Je crois qu'il faut utiliser des messages) En revanche, ton problème ne sera pas résolu si c'est ton 2ème programme qui est kill.
Picsonald
Messages postés23Date d'inscriptionlundi 30 décembre 2002StatutMembreDernière intervention 7 novembre 2020 23 févr. 2009 à 22:05
En tout cas, il semblerait que beaucoup de programme adoptent cette solution. Un deuxième programme de crash report est exécuté pour diagnostiquer un plantage.
Et bien merci de votre aide, j'essaye de voir ce que ça donne avec ce que vous m'avez proposé ! Merci !!!