2008-10-03 7 views
4

Est-il vraiment nécessaire de libérer des composants COM de Office PIA, lorsque vous n'en avez plus besoin en appelant Marshal.ReleaseComObject (..)?Publication des composants COM

J'ai trouvé des conseils variés et contradictoires sur ce sujet sur le web. À mon avis, puisque Outlook PIA renvoie toujours une nouvelle référence à ses interfaces comme renvoyant des valeurs de ses méthodes, il n'est pas nécessaire de le libérer explicitement. Ai-je raison?

Répondre

1

Avec Microsoft Office, en général, vous avez besoin de libérer explicitement vos références, ce qui peut être effectué en toute sécurité en deux étapes:

(1) Première sortie tout l'objet mineur auquel vous ne tenez pas nommé variable d'objet via un appel à GC.Collect() puis GC.WaitForPendingFinalizers(). (Vous devez appeler cela deux fois, si les objets concernés peuvent avoir des finaliseurs, comme lors de l'utilisation de Visual Studio Tools pour Office (VSTO).)

(2) Ensuite, publiez explicitement les objets auxquels vous détenez une variable nommée via un appel à Marshall.FinalReleaseComObject() sur chaque objet.

C'est tout. :-)

J'ai discuté ceci plus en détail in a previous post, avec un exemple de code.

+0

Mike, commenterais-tu celui-ci: http://stackoverflow.com/questions/159313/runtime-callable-wrapper-rcw-scope-process-or-or-application-domain –

1

Il y a quelques bonnes pratiques here à l'aide d'un wrapper..worth géré la vérification des ..

+0

Merci, c'est un bon article. Mais, j'ai besoin de savoir que je dois explicitement libérer le composant COM du PIA Office existant, pas pour créer mon propre wrapper. –

0

Peut-être juste ma superstition, mais j'ai décidé de libérer explicitement l'Office PIA via Marshal.ReleaseComObject() parce que quand ma demande écrasé, les références à Excel et Word restaient ouvertes. Je n'ai pas creusé trop profondément pourquoi (les délais imbéciles), mais les libérer dans le cadre de la disposition de ma classe a résolu ce problème.

2

Les assemblys PIA sont des wrappers Interop .NET. Cela signifie que dans le destructeur de l'objet (ou Dispose - je ne me souviens plus) il gèrera automatiquement son nombre de références. L'astuce est que certaines références ne seront pas libérées tant que le garbage collector ne sera pas exécuté. Cela dépend de ce que l'objet COM instancie. Par exemple, un objet COM qui ouvre les curseurs de base de données conservera ces curseurs en mémoire jusqu'à ce que le nombre de références sur ces curseurs soit libéré. Avec l'interopérabilité .NET/COM, les références ne sont pas libérées jusqu'à ce que le garbage collector s'exécute ou que vous publiez explicitement la référence en utilisant Marshal.ReleaseComObject (ou FinalReleaseComObject).

Personnellement, je n'ai pas travaillé avec les PIA Microsoft Office, mais dans la plupart des circonstances, vous ne devez pas avoir pour publier explicitement les références. Ce n'est que lorsque votre application commence à verrouiller d'autres ressources ou se bloque que vous devriez commencer à se méfier des références qui pendent.

EDIT: Si vous exécutez dans une situation où vous avez besoin de nettoyage des objets COM/Interop, utilisez Marshal.FinalReleaseComObject - qui prend la référence compte tout le chemin à zéro au lieu de simplement décrémentation par un - et définir la référence d'objet à null. Vous pouvez forcer forcer la collecte de place (GC.Collect) si vous vraiment voulez être sûr, mais faites attention à GC trop souvent car il invoque un coup de performance notable.

0

Vous devez le faire si vous souhaitez quitter l'instance de l'application Office, comme décrit dans this post.

Et il est difficile de bien faire les choses dans tous les scénarios, sauf les plus simples.

+0

Mais, dans le cas où j'omets un code de nettoyage, rien ne se passe mal. Outlook se ferme même plus rapidement dans ce cas, et j'ai trouvé quelques articles sur le web qui indiquent qu'il n'est pas nécessaire de libérer un objet COM Outlook. –

0

Mon expérience montre que vous devez, sinon (au moins Outlook) l'application peut ne pas fermer du tout.

Mais cela ouvre une autre boîte de Pandore, car il semble que les RCW sont par processus, donc vous pouvez casser un autre addin, qui se trouve avoir une référence au même objet.

J'ai posté une question connexe here, mais je n'ai toujours pas de réponse claire. Je modifierai ce post une fois que j'en saurai plus.

0

Il existe une règle simple à propos de .Net/COM interop - En cas de doute, toujours Release(). :-)

Questions connexes