GC.Collect() et Finaliser
Ok, il est connu que la GC appelle implicitement Finalize
méthodes sur des objets lors de l'identification de l'objet en tant que déchets. Mais qu'advient-il si je fais une GC.Collect()
? Sont les finaliseurs encore exécuté? Une question stupide peut-être, mais quelqu'un m'a demandé ce et j'ai répondu un "Oui" et puis j'ai pensé: "a Été entièrement correcte?"
- Pourquoi vous n'essayez pas de le faire en faisant des journaux dans le destructeur de voir n' "Finaliser" appelé ou pas? ou j'ai raté quelque chose?!
- Ce n'est certainement pas une "question stupide".
- Oui j'ai pu le faire, et éviter de poster la question. Mais alors la connaissance serait juste de les confiner à moi. La bonne partie de est - en le postant ici, j'ai eu de plus d'élaborer des réponses sur le sujet, et j'espère que cela aidera d'autres utilisateurs de trop!
- Voir aussi: Sont .net finaliseurs toujours exécuté?
Vous devez vous connecter pour publier un commentaire.
Pas de pas de pas de. Ce n'est pas connu parce que, pour être connaissances une déclaration doit être vrai. Cette déclaration est faux. Le garbage collector ne pas exécuter les finaliseurs retraçant, qu'il exécute lui-même ou si vous appelez
Collect
. Le finaliseur thread exécute les finaliseurs après le tracé du collecteur a trouvé la poubelle et ce qui se passe de manière asynchrone à l'égard d'un appel àCollect
. (Si ça arrive, qu'il ne pourrait pas, comme une autre réponse souligne.) Qui est, vous ne pouvez pas compter sur le finaliseur thread d'exécution avant le retour du contrôle deCollect
.Voici une esquisse schématique de la façon dont il fonctionne:
Comme je l'ai dit, c'est simplifiée à l'extrême; les détails de la façon dont le finaliseur file d'attente de travaux sont un peu plus compliquées que cela. Mais il devient assez de l'idée à travers. La conséquence pratique est ici que vous ne pouvez pas supposer que l'appel
Collect
gère également les finaliseurs, car il n'a pas. Permettez-moi de le répéter, une fois de plus: le tracé partie du garbage collector ne pas exécuter les finaliseurs, etCollect
ne fonctionne que le traçage partie du mécanisme de collecte.Appel de la bien nommée
WaitForPendingFinalizers
après l'appel deCollect
si vous voulez vous assurer que tous les finaliseurs ont couru. Qui va interrompre le thread courant jusqu'à ce que le thread finaliseur se déplace à vider la file d'attente. Et si vous voulez vous assurer que ceux finalisé les objets ont leur mémoire récupérée, alors vous allez avoir à appelerCollect
un deuxième temps.Et bien sûr, il va sans dire que vous ne devriez faire cela pour le débogage et le test. Ne jamais faire de ce non-sens dans le code de production sans vraiment, vraiment une bonne raison.
En réalité la réponse: "Ça dépend". En fait il y a un thread qui exécute tous les finaliseurs. Cela signifie que l'appel à
GC.Collect
seulement déclenché ce processus et l'exécution de toutes les finaliseurs serait appelée de façon asynchrone.Si vous voulez attendre jusqu'à ce que tous les finaliseurs serait appelé vous pouvez utiliser l'astuce suivante:
IDisposable.Dispose
(idéalement par une instruction d'utilisation) à la place.Oui, mais pas tout de suite. Cet extrait est tiré de La Collecte des ordures: Gestion Automatique de la Mémoire dans le Microsoft .NET Framework (MSDN Magazine) (*)
(*) À partir de novembre 2000, donc les choses ont peut être changé depuis.
Lorsque les ordures sont collectées (que ce soit en réponse à la sollicitation de la mémoire ou
GC.Collect()
), les objets nécessitant une finalisation sont mis à la file d'attente de finalisation.Sauf si vous appelez
GC.WaitForPendingFinalizers()
, les finaliseurs peut continuer à s'exécuter dans le contexte de temps après la collecte des ordures a fini.BTW, il n'y a aucune garantie finaliseurs sera appelé à tous les. De MSDN...
Couple de plus de points valent la peine d'état ici.
Finalizer est le dernier point où .net les objets peuvent libérer des ressources non managées.
Les finaliseurs doivent être exécutées uniquement si vous ne jetez pas votre cas correctement. Idéalement, les finaliseurs doit jamais être exécutée dans de nombreux cas. Parce que les règles de disposer de la mise en œuvre devrait supprimer la finalisation.
Voici un exemple pour corriger IDispoable mise en Œuvre.
Si vous appelez la méthode dispose de tout jetable objets, il est conseillé de désactiver toutes les références et la Suppression de la finalisation. Si il n'est pas si bon développeur qui a oublier d'appeler la méthode dispose, Finalizer est la vie de veille.