La Libération D'Objet Excel Dans Mon Destructeur
Je suis en train d'écrire une classe à l'aide d'Excel de Microsoft.Interropt.Excel DLL.
J'ai fini toutes les fonctions, mais j'ai une erreur dans mon Destructeur.
Je Veux enregistrer toutes les modifications apportées à mon dossier et je tiens à la libération de tous les source de. Je veux tous dans mon destructeur.
Mais Dans mon destructeur, Excel.ApplicationClass, Classeur et de la Feuille de calcul les objets sont remplis par une Exception qui ont le message "un objet COM qui a été séparé de son RCW sous-jacent ne peut pas être utilisé."
Donc je ne peux pas enregistrer de rien, près de rien, car je ne peux pas accéder classeur ou un objet de feuille de calcul.
Ne puis-je pas accéder aux membres privés de la classe dans le Destructeur?
OriginalL'auteur Murat | 2010-01-18
Vous devez vous connecter pour publier un commentaire.
La chose la plus proche que .NET est un destructeur, est ce que .NET appelle un finaliseur. La principale différence est qu'un destructeur de a généralement finalisation déterministe (par exemple, lorsque le nombre de références sur l'objet devient égale à zéro), tout en un .NET finaliseur est appelé à un indéterminée de temps après que l'objet n'est plus référencé. Ceci est géré par le .NET Garbage Collector à l'aide d'une des racines de suivi de la procédure, plutôt que d'utiliser le simple comptage de référence.
L'un des meilleurs articles sur ce est La Collecte des ordures: Gestion Automatique de la Mémoire dans le Microsoft .NET Framework. Pour en savoir plus sur les finaliseurs en particulier, consultez l'article Finaliser les Méthodes et les Destructeurs dans MSDN.
Non, vous ne pouvez pas le faire en toute sécurité.
Ce qui se passe dans votre cas, c'est que lorsque votre objet n'est plus, directement ou indirectement, référencé par la racine, les objets COM votre les références de l'objet-qui est, les objets référencés par votre champs privés, sont également pas référencé par une racine. (Cours de référence de votre objet champs ne pas garder ces objets COM en vie parce que votre objet n'est plus référencé par, ou tracé de, une racine, et, par conséquent, les objets COM ne sont pas de trace à partir d'une racine.) Si votre objet et tous les objets COM il les références sont tous prêts à être nettoyée en même temps. Quelques temps plus tard, le garbage collector de nettoyage de votre objet et l'appel de son finaliseur, comme il le fera aussi avec les objets COM, chaque de ce qui est vraiment un Runtime Callable Wrapper (RCW).
Le problème, c'est que non seulement le timing de ces objets doivent être des ordures collectées incertain, mais les ordre dans lequel les finaliseurs sont appelés également de façon non déterministe. Dans ce cas, une Exécution Callable Wrapper dispose également d'un outil de finalisation, qui appelle Maréchal.ReleaseComObject sur lui-même, ce qui a pour résultat de le décrémenter le compteur de référence de la COM côté de la clôture, de sorte que cet objet peut être libéré. Mais puisque l'ordre dans lequel les finaliseurs sont appelés est incertain, il est très possible que les finaliseurs pour les objets COM qui votre objet les références à feu avant le finaliseur pour votre objet. Donc le code à l'intérieur de votre finaliseur pourrait travail parfois, mais, la plupart du temps, l'un ou plusieurs des Runtime Callable Wrappers de vos références d'objets ont déjà eu leur finaliseurs appelé, et le sous-jacent COM objet aura été publié, avant votre finaliseur obtient exécuter son code.
En bref, vous devez éviter d'utiliser les finaliseurs en général, et vous devriez ne jamais accéder à des types de référence à partir de l'intérieur d'un finaliseur, parce que ces types de référence ont déjà été finalisés.
Pour remédier à votre situation, je voudrais envisager deux possibilités:
Disposer des objets COM dans la même méthode que les crée. J'ai un couple de discussions sur ce ici et ici.
Permettre déterministe de l'élimination de votre objet en faisant usage de la Interface IDisposable, au lieu de s'appuyer sur le non-déterministe finalizer.
Pour les articles sur la façon de mettre en œuvre la IDisposable modèle, voir:
(Rohit Gupta)
-- Mike
OriginalL'auteur Mike Rosenblum
Je ne suis pas sûr si je suis codage quelque chose de mal, a tenté de suivre les exemples ici. J'ai constaté que lorsque je profite de l'IDisposable modèle tout fonctionne, sauf si j'ai besoin de gérer classeur événements.
Dans mon scénario, l'utilisateur peut fermer le Classeur avant de fermer l'application. J'ai déclaré objet Excel WithEvents et codé les WorkbookBeforeClose gestionnaire pour répondre aux exigences.
Dans ce scénario-je obtenir le "un objet COM qui a été séparé de son RCW sous-jacent ne peut pas être utilisé" erreur quand je vais fermer mon application (et j'ai déjà fermé l'Excel). L'erreur se produit dans le Finaliser lorsqu'il appelle dispose(False).
Le problème disparaît si je laisse l'objet Excel déclaré avec des événements, mais de ne pas le code de n'importe quel gestionnaire.
Dans mes Disposer j'ai dû avaler l'erreur de mes Classeurs.Fermez et Quittez qu'ils étaient les déclarations qui ont provoqué l'erreur.
OriginalL'auteur sdmcnitt
Non, vous ne pouvez pas accéder à l'un quelconque des objets gérés dans un destructeur: cela inclut COM Rcw.
Au lieu de cela, l'application de la norme IDisposable modèle et de publier vos objets COM dans la méthode dispose(bool) comme vous le feriez d'un revenu d'objets gérés.
OriginalL'auteur Joe