9
votes

Comment puis-je détruire des objets COM dans C #?

Quelles sont les méthodes pour détruire des objets Interop Excel Com dans C #, en plus de ceux-ci:

object_instance = null;
System.GC.collect();
&
System.Runtime.InteropServices.Marshal.ReleaseComObject(object);


7 commentaires

Pourquoi avez-vous besoin de - dans la plupart des cas, le cadre devrait prendre en charge cela pour vous?


objet_instance = null; ne détruit pas l'objet en passant. Il ne garantit même pas qu'il s'agisse d'une poubelle collectée (c'est-à-dire parce que quelque chose d'autre pourrait toujours y tenir une référence)


J'ai un problème avec mon programme Excel où l'objet Undeleted causait régulièrement, vous pouvez dire "scintillation", après avoir cherché une chaîne


@Peril, vous auriez dû mentionner au début que vous travaillez dans Excel. Excel est une application COM; Ce n'est pas géré le code et ce n'est pas .net. Vous devriez toujours suivre les règles .NET dans .net, mais obtenir Excel pour libérer des références est un problème totalement différent. Retarder votre message pour refléter cela.


Merci, j'apprécierais si vous pouvez suggérer une autre méthode d'Excel ..


En tant qu'avort: appeler system.gc.collect () manuellement presque toujours entraînera une performance médiocre et une utilisation accrue de la mémoire pour votre demande. Je conseillerais fortement contre ça!


Marshal.ReleasecomObject (objet); semble être la solution correcte, pourquoi demandez-vous "en plus de ceux-ci"?


6 Réponses :


15
votes

Le collecteur des ordures est le seul mécanisme qui peut détruire un objet géré , mais vous ne l'invoquez généralement pas explicitement. Vous venez de le laisser faire sa chose.

Tout comme si vous ne prenez jamais votre propre poubelle au dépôt, vous laissez simplement rester assis sur le coin. C'est toujours la responsabilité de l'homme des ordures.

Vous pouvez libérer des références à des choses et les nettoyer avec des produits fonctionnels, des finaliseurs et des destructeurs, mais ne les détruisez pas.

à l'aide de system.gc Vous pouvez demander à l'homme de la poubelle de faire les choses tôt - Demander une course personnalisée juste pour vous-même - mais cela revient généralement de son emploi du temps et il a beaucoup plus de déchets à gérer que ce n'est pas le vôtre que ce n'est pas le cas. conseillé.


5 commentaires

Pas du tout, mais j'étais mi-édition, l'a détruit accidentellement mais le remettez-le.


Il y a peu de casses où vous devez supprimer explicitement l'objet ....... Bien que je ne sois pas capable de vous montrer mon programme mais peut vous assurer que j'ai vraiment besoin de détruire l'objet ..


"Mais cela vissait généralement son emploi du temps et il a beaucoup plus de déchets à gérer que le vôtre, il n'est donc pas recommandé." Les réponses valent une +1 juste pour ça - une excellente réponse quand même


@Peril parle-t-on d'un objet géré ou non géré? Comme le dit JDK, utilisez Idisposable pour des objets non gérés. Détruire explicitement des objets gérés n'est pas possible à ma connaissance, mais peut-être un peu plus de détails sur Que voulez-vous détruire serait utile. Tout comme devinez, s'il s'agit d'une chaîne liée à la sécurité dont il suffit de rester en mémoire très peu de temps, regardez Securstring. En outre, les flux (c'est-à-dire MemoryStream) peuvent être explicitement disposés à mes connaissances.


@Peril Brain: I + 1'd votre commentaire parce que je vois de l'endroit où vous venez. Heureusement, beaucoup d'autres ont vu l'utilité de répondre à votre question sur la manière dont vous pouvez "détruire" des objets.



16
votes

Le kicker est que si vous n'avez pas laissé tomber toutes les références à l'objet, même GC.Collect ne le détruirez pas.

La règle en C # (ou .NET Généralement) est que vous ne pouvez pas être un objet Destory. Disposer () ne le ferai pas. Un finaliseur ne le fera pas (règle numéro 2, n'utilisez pas de finaliseur à moins que vous sachiez pourquoi vous en avez besoin et que vous n'appelez jamais directement).

Pour .NET, ce sont les choses que vous devez faire:

  1. Si un objet contient des références à des objets non gérés, implémentez l'Idisection du modèle. Et la mettre en œuvre complètement; Il s'agit plus que de simplement fournir une méthode de Dispose ().
  2. La seule raison d'avoir un finaliseur est de libérer des objets non gérés et uniquement dans le cas où votre objet n'a pas été correctement disposé. Une fois que votre méthode de disposition est appelée, il devrait faire le nettoyage, puis "tuer" le finaliseur en appelant gc.suppressFinalize.
  3. Si vous utilisez un objet qui implémente une méthode Dispose (), appelez () lorsque vous avez terminé avec cet objet. Les meilleures pratiques consistent à allouer cet objet avec un bloc d'utilisation. La sortie de l'utilisation du bloc appellera Disposer () automatiquement.
  4. Lorsque vous avez terminé avec un objet, supprimez toutes les références à l'objet, y compris les gestionnaires d'événements, les délégués, etc.
  5. Au-delà de cela, faites confiance au collectionneur des ordures pour faire son travail. Ne plaisante pas avec le collecteur des ordures; Vous n'êtes probablement susceptible de faire pire des choses, à moins que vous ne sachiez vraiment vraiment ce que vous faites et pourquoi.

4 commentaires

+1 - Belle réponse! Je qualifierais n ° 1 pour inclure des ressources. Si votre classe détient une référence à un objet géré qui implémente Idisose, vous souhaitez également mettre en œuvre le modèle d'élimination. Généralement, cette classe jetable représentera une ressource externe limitée ou coûteuse.


Qu'en est-il du maréchal.ReleasecomObject?


@Sergey, désolé, je suis à peu près désemparé des problèmes de COM.


Qu'est-ce que cette réponse a à voir avec les objets COM? Cela semble être juste une réponse générique sur la collection de la poubelle C #



0
votes

Si votre objet attribue des ressources significatives, il est préférable de mettre en œuvre des appels isisposables et explicitement décisifs. Si vous ne pouvez pas appeler, éliminer pour une raison quelconque et que votre classe se réserve une mémoire non giquante, vous pouvez utiliser GC.AddMemoryPressure (avec une saisie gc.removememororyPressure correspondante dans le finisseur) pour indiquer à la GC votre classe est plus lourde qu'il n'y paraît, la hiéricorise pour plus tôt. Nettoyage.


0 commentaires

2
votes

Pour la plupart, vous devez supprimer toutes les références à un objet. Ce n'est qu'alors que le collecteur des ordures le verra et le détruira.

Soyez conscient de ceci: xxx

tout cela est tuer la référence objet_instance. Cela fonctionne si c'est la seule référence. S'il y a d'autres références, il ne sera pas collecté. xxx

... xxx


0 commentaires

0
votes

Si vous avez vraiment besoin de libérer explicitement la mémoire occupée par un objet et que vous êtes sûr que vous choisirez le moment pour l'exterminer mieux que GC, la seule option raisonnable est de l'affecter sur la pile et de le laisser mourir quand Vous revenez de la méthode où il a été alloué.


0 commentaires

0
votes

Si vous voulez contrôler afin que vous puissiez gérer des ressources de l'objet, implémentez l'interface Idisposable.

http://msdn.microsoft.com/en-us /Library/system.idisposable.aspx

Si les ressources ne sont pas la raison pour laquelle vous souhaitez contrôler explicitement la destruction de l'objet, je ne peux pas comprendre pourquoi vous voulez ce niveau de contrôle ... utilisez-vous la mise en commun des objets?


0 commentaires