10
votes

Finisseur non appelé

J'ai une classe en C # où je veux fermer correctement certains ports de communication lorsque ma classe est éliminée. Cependant, le finaliseur n'est jamais appelé lorsque je quitte le programme. Pourquoi donc? Est-ce que je fais quelque chose de mal?

J'appelle le dispositif de disposer manuellement qui passe et ferme toutes les communications. Ceci n'est pas déclenché non plus.

Voici le finaliseur que j'utilise: xxx


1 commentaires

Je suppose que votre problème n'est pas où vous le pensez. Il est difficile de dire sans voir plus de votre programme, cependant.


3 Réponses :


0
votes

Le finaliseur est appelé par le collecteur des ordures et la collecte des ordures n'est pas un processus prévisible, il n'est donc pas très fiable. Vous devez déterminer d'autres moyens pour disposer de vos ressources.


6 commentaires

C # n'a pas de destructeurs. Ces choses qui utilisent la syntaxe C ++ Destructor - ils sont finaliseurs .


L'OP faisait référence à cela comme destructeur et a ensuite été édité.


@Ben Voigt: En fait, le guide de programmation C # appelle les destructeurs: MSDN.MicRosoft. com / fr-nous / bibliothèque / 66x5fx1b.aspx


@Ben: Ils sont appelés "destructeurs" dans C # et "finaliseurs" dans le CLR. Il est regrettable que les deux équipes ont choisi une terminologie différente; Si nous devions tout recommencer, nous essaierions probablement d'être plus cohérent. Mais il est tout à fait faux de dire que c # n'a pas de destructeurs. C # a destructeurs; La spécification appelle les destructeurs, la documentation appelle les destructeurs et ils sont mis en œuvre en remplaçant le finaliseur.


@ERIC: La documentation est fausse à plat. Il est indiqué que "la syntaxe destructeurs en C # et C ++" sont équivalentes. J'ai déjà déposé les commentaires de la documentation. Je pense qu'il est correct de dire que "en C #, la syntaxe de destructeurs C ++ est utilisée pour créer un finaliseur CLR". C'est destructeurs syntaxe , peut-être que cela peut même être appelé "C # destructeur", mais ce n'est pas un destructeur dans le sens général. Je vais donc continuer à encourager les gens à utiliser le mot finaliseur , c'est sans ambiguïté et évidemment lié à finalisation dans les spécifications C # et CLR.


@Ben: Je vous encourage à le faire si cela vous rend heureux. En ce qui concerne la documentation, je suppose que la ligne que vous êtes en colère est "fournit un contrôle implicite en mettant en œuvre la finalisation protégée sur un objet (syntaxe destructeur en C # et C ++)". Bien que cette phrase soit écrite maladive et probablement pas grammaticale, je ne vois aucune erreur dedans, de côté du fait qu'il aurait probablement dû dire que c ++ / cli plutôt que juste C ++. Je n'aurais pas utilisé de parenthèse; J'aurais écrit deux phrases.



11
votes

Le finaliseur (qui est ce que vous utilisez ici) n'est appelé que pendant la phase de finalisation, qui se produira pendant la GC.

Si vous implémentez correctement, cela ne devrait jamais être appelé. Je couvre cela en détail sur Ma série sur Idisposable .

Cela étant dit, si vos "ports de communication" sont manipulés via des classes gérées, vous ne devez pas utiliser un finaliseur du tout. Cela ajoute des frais généraux qui ne vous aident pas quoi que ce soit. Il suffit de mettre en œuvre Idisposable (correctement) et laissez les emballages gérés autour des classes de port gérer la finalisation si nécessaire.


2 commentaires

Comment puis-je implémenter «correctement» isisposable? Ma classe hérite d'UserControl. Je pensais que la mise en œuvre est-elle imprenable? Clairement, je me trompe peut-être.


@Spenduku: Je recommanderais de lire mes articles liés ci-dessus. J'explique cela en détail, y compris la sous-classement d'une classe Idisposable. Quelle classe utilisez-vous pour vos "ports"?



7
votes

Si un arbre tombe dans la forêt avec personne autour d'entendre, cela fait-il un son? Assurez-vous que cela fait:

using System;

class Program {
    static void Main(string[] args) {
        new Test();
    }
}

class Test {
    ~Test() { Console.Beep(); }
}


1 commentaires

Et que se passe-t-il lorsque vous avez mis de nouveau test () dans une autre fonction statique, appelez cette nouvelle fonction statique de Main, et Application.Run (nouveau formulaire1 ()) à l'intérieur de la principale? Je doute fortement GC finalisera cette classe de test jusqu'à la fermeture de l'application ou appelez gc.Collect (); ;)