Classe de fichiers Log : utilisation d'un destructeur.

Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Dernière intervention 7 novembre 2020 - 18 févr. 2009 à 15:44
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Derniè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...

Auriez-vous une petite solution a me proposer ?

Merci d'avance pour votre aide.

Pics'

9 réponses

cs_casy Messages postés 7741 Date d'inscription mercredi 1 septembre 2004 Statut Membre Dernière intervention 24 septembre 2014 40
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.

---- Sevyc64  (alias Casy) ----<hr size="2" width="100%" /># LE PARTAGE EST NOTRE FORCE #    http://aide-office-vba.monforum.com/index.php
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Derniè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...

Pics'
0
RougailSaucisse Messages postés 118 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 6 décembre 2010 1
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.

Voili voilou
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Derniè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'
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
krimog Messages postés 1860 Date d'inscription lundi 28 novembre 2005 Statut Membre Dernière intervention 14 février 2015 50
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).

Krimog :
while (!succeed = try()) ;
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Derniè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...

Any idea ?

Pics'
0
RougailSaucisse Messages postés 118 Date d'inscription lundi 16 février 2009 Statut Membre Dernière intervention 6 décembre 2010 1
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() ^^
0
krimog Messages postés 1860 Date d'inscription lundi 28 novembre 2005 Statut Membre Dernière intervention 14 février 2015 50
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.

Krimog :
while (!succeed = try()) ;
0
Picsonald Messages postés 23 Date d'inscription lundi 30 décembre 2002 Statut Membre Derniè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 !!!

Pics'
0