Pourquoi mon destructeur de ne jamais exécuter?
J'ai un vide Winform avec un destructeur de la méthode
public partial class Form1 : Form
{
public Form1()
{
System.Diagnostics.Trace.WriteLine("Form1.Initialize " + this.GetHashCode().ToString());
InitializeComponent();
}
~Form1()
{
System.Diagnostics.Trace.WriteLine("Form1.Dispose " + this.GetHashCode().ToString());
}
}
Lorsque le formulaire est détruit, je veux écrire dans la fenêtre de sortie:
(Form1 ouvert) Form1.Initialiser 41149443 (Form1 fermé) Form1.Disposer 41149443
MSDN suggère 3 façons dans la mise en œuvre destructeur:
- ~Destructeur()
http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx - IDisposable
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx - SafeHandle modèle
http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx
Cependant, aucune de ces façons d'écrire "Form1.Disposer 41149443" de la Fenêtre de sortie.
Par conséquent, je ne suis pas capable de dire si le formulaire a été détruit ou pas. Des Suggestions ?
Dois-je renoncer à l'espoir sur la réalisation de ce en raison de l'incertitude de garbage collector?
Est-il un autre moyen de savoir si Form1 a été nettoyée ?
Pourquoi? Qu'essayez-vous de faire?
Vous ne pouvez pas supposer que le destructeur sera appelé. (Par exemple, si vous avez assez de mémoire, il est parfaitement valable de ne jamais appeler n'importe quel destructeur, jamais.)
N'est-ce pas la trace écrite?
Suivi de sortie n'a pas "Form1.Disposer 41149443" écrit
Ne vous rincer la sortie de trace avant que l'application est terminée? Sinon, votre trace pourrait être nettoyée avant de l'écrire.
Vous ne pouvez pas supposer que le destructeur sera appelé. (Par exemple, si vous avez assez de mémoire, il est parfaitement valable de ne jamais appeler n'importe quel destructeur, jamais.)
N'est-ce pas la trace écrite?
Suivi de sortie n'a pas "Form1.Disposer 41149443" écrit
Ne vous rincer la sortie de trace avant que l'application est terminée? Sinon, votre trace pourrait être nettoyée avant de l'écrire.
OriginalL'auteur Jeson Martajaya | 2011-08-03
Vous devez vous connecter pour publier un commentaire.
Seulement l'une des trois façons de mettre en œuvre un destructeur qui vous liste implique, en réalité, un destructeur, et c'est
~Destructor()
.Si vous mettez en œuvre
IDisposable
, et de disposer de votre objet, puis le code de laDispose
fonctionnera, mais il n'y a pas de raison de penser que votre destructeur de la volonté.Je pense que vous courir après l'impossible ici. Les destructeurs exécuter lorsque le garbage collector, donc de décrets. Ce n'est pas quelque chose que vous avez aucun contrôle sur. La GC est bien dans son droit à se former une opinion, que l'exécution des destructeurs simplement perdre du temps, et si il ya beaucoup de mémoire, il forme à cette opinion.
Si vous avez besoin d'prévisible de l'élimination, la finalisation etc., ensuite, utilisez
IDisposable
.De quoi parles-tu?
Dispose
fonctionne quand il est appelé, toujours viausing
. Où ai-je dis queDispose
irait automatiquement?Vous avez écrit "si vous avez besoin d'prévisible disposition...". Si vous n'utilisez pas l'aide ou appeler explicitement, il n'est pas appelé. Comme je n'ai jamais utilisé l'aide d'un formulaire, c'est encore moins prévisible que le finalizer.
Oui, et il n'appelle PAS le finaliseur!!!! C'est pourquoi je ne dirais pas que c'est prévisible disposition. C'est juste une configuration standard pour travailler avec des ressources non managées et toute la classe qui a un finaliseur devrait mettre en œuvre l'IDisposable modèle. Mais à mon avis, cette réponse n'est pas une réponse à la question ci-dessus.
J'ai même dis dans la réponse que le finaliseur ne fonctionne pas.
OriginalL'auteur David Heffernan
Sauf si vous êtes l'étude de la collecte des ordures, un destructeur n'est pas le lieu pour votre suivi. Vous devriez chercher à Éliminer (ce qui est substituables dans la Forme). Cela se produit après le non géré ressources (comme votre poignée de la fenêtre) a été publié.
Si vous voulez voir si une forme de contrôle/il a été disposé, à l'utilisation de la
Control.IsDisposed
propriété.Edit: en Raison de
GC.SuppressFinalize
, votre méthode Finalize (destructeur de syntaxe en C#) ne s'exécutera jamais si dispose est appelé explicitement (ou le cadre).Pour plus d'informations, voir Mise en œuvre d'une Méthode dispose.
"Form1.Dispose " + (disposing ? "disposing " : "")
merci. fixe
mon point est que ce qui est appelé par le finaliseur seulement si nécessaire. Si quelqu'un dispose de la forme explicitement, le destructeur (finilize méthode) probablement jamais est exécuté en raison de la GC.SupressFinalize. Voir le modèle dispose pour plus d'info.
Vous avez raison, je n'ai pas vu qui Dispose() avec le paramètre booléen est réellement mis en œuvre dans la classe de Formulaire. Par conséquent, votre Disposer va être appelée à partir de l'outil de finalisation ou de la méthode de base. Mais vous devriez TOUJOURS faire appel à la base.Dispose(disposing); lorsque vous remplacez cette méthode.
OriginalL'auteur agent-j
Oui, vous devriez sans doute renoncer à l'idée d'un destructeur, parce qu'ils sont non-déterministe de la nature. Je ne suis pas sûr pourquoi vous devez avoir la forme éliminés plutôt que de simplement fermé, mais simplement de clôture, il devrait être suffisant dans la plupart des cas.
Vous pouvez utiliser
IDisposable
mais cela dépend de pourquoi vous avez besoin de la forme à ordures. Si vous avez besoin de ré-utiliser, il suffit de créer une autre instance.OriginalL'auteur kprobst
Le Formulaire est à ordures collectées lors de l'absence de références existent et que le garbage collector arrive à courir. Vous pouvez forcer le garbage collector en appelant GC.Collect().
Vous ne devriez pas référence à un autre objet à l'intérieur d'un Finaliseur (aka le destructeur) parce que l'objet pourrait avoir été nettoyée déjà.
Vous pouvez utiliser de la mémoire de l'analyseur d'outils pour savoir si votre objet est le garbage collector ou pas, si vous en avez vraiment besoin.
Vous devez également garder à l'esprit que le finaliseur est appelé à partir d'un thread autre que le thread principal.
EDIT:
Si votre problème est tout simplement que vous ne voyez pas la trace de sortie, vous pourriez avoir à tourner autoflush sur
EDIT 2:
Il y a peut être une référence externe à votre formulaire, comme un régime enregistré d'un gestionnaire d'événement. Je vous suggère d'ajouter un bouton dans une zone d'administration de votre application qui exécute le code suivant:
Comme ce le garbage collector devez exécuter et de détruire votre formulaire (définir un point d'arrêt dans le finaliseur). Si non, vous avez une référence à l'objet qui doit être détruit.
Ok, essaye de faire de mon 2ème deviner. Peut être avez vous quelques références à la forme.
J'ai essayé la 2ème option et cela a fonctionné. Je pense que le vôtre est le plus proche de réponse compare à d'autres.
OriginalL'auteur slfan
Ajouter un FormClosed événement pour le concepteur.
ie:
Puis créer la fonction appropriée pour gérer l'événement.
OriginalL'auteur Vincent DeCampo
Vous pourriez essayer d'emballage de votre formulaire dans un WeakReference objet, puis vérifier son IsAlive propriété afin de déterminer si elle a été nettoyée. Mais, oui,...comme pour les autres réponses, vous pouvez être mieux de le laisser et faire confiance à la GC pour faire son travail!
OriginalL'auteur IanR