2009-12-02 2 views
6

J'ai lu beaucoup d'articles sur le net sur la libération de RCW en toute sécurité, et il me semble que personne ne peut être d'accord sur exactement ce qui doit être fait dans quel ordre, donc je Je vous demande les gars pour vos opinions. Par exemple, on pourrait le faire:Libérer une référence d'objet COM en toute sécurité à partir de .NET

object target = null; 
try { 
    // Instantiate and use the target object. 
    // Assume we know what we are doing: the contents of this try block 
    // do in fact represent the entire desired lifetime of the COM object, 
    // and we are releasing all RCWs in reverse order of acquisition. 
} finally { 
    if(target != null) { 
     Marshal.FinalReleaseComObject(target); 
     target = null; 
     GC.Collect(); 
     GC.WaitForPendingFinalizers(); 
    } 
} 

Cependant, certaines personnes préconisent de faire la collecte des ordures avant Marshal.FinalReleaseComObject, certains après, et d'autres pas du tout. Est-il vraiment nécessaire de GC manuellement chaque RCW, surtout après qu'il a déjà été détaché de son objet COM?

À mon avis, il serait plus simple et plus facile à détacher juste le RCW de l'objet COM et laisser le RCW expirer naturellement:

object target = null; 
try { 
    // Same content as above. 
} finally { 
    if(target != null) { 
     Marshal.FinalReleaseComObject(target); 
    } 
} 

Est-il suffisant pour le faire?

Répondre

12

Pour que votre référence à l'objet COM cible libéré, il suffit et préféré pour appeler juste Marshal.FinalReleaseComObject et pas forcer un Collect. En d'autres termes, vous vous êtes acquitté de votre responsabilité de publier votre référence dès que vous en auriez fini avec elle. Je ne vais pas toucher à la question de FinalReleaseComObject vs ReleaseComObject. Cela laisse la plus grande question de savoir pourquoi les gens préconisent d'appeler GC.Collect() et WaitForPendingFinalizers()?

Parce que pour certaines conceptions, il est difficile de savoir quand il n'y a plus de références managées, donc vous ne pouvez pas appeler en toute sécurité ReleaseComObject. Vous avez deux choix, laissez la mémoire s'accumuler et espérez qu'une collecte se produise ou force une collecte. [Voir la note de vote de Steven Jansen dans les commentaires]

Une note supplémentaire est que le réglage target à null est généralement inutile, et est spécifiquement inutile dans votre exemple de code. Définir des objets sur rien est une pratique courante pour VB6 puisqu'il utilise un garbage collector basé sur le nombre de références. Le compilateur pour C# est assez intelligent (lors de la construction pour la version) pour savoir que target est inaccessible après sa dernière utilisation et pourrait être GC'd, même avant de quitter la portée. Et par dernière utilisation, je veux dire la dernière utilisation possible donc il y a des cas où vous pourriez le mettre à null. Vous pouvez voir par vous-même avec le code ci-dessous: Si vous construisez la libération (par exemple, le SCC GCTest.cs)

using System; 
    class GCTest 
    { 
     ~GCTest() { Console.WriteLine("Finalized"); } 
     static void Main() 
     { 
      Console.WriteLine("hello"); 
      GCTest x = new GCTest(); 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 
      Console.WriteLine("bye"); 
     } 
    } 

, « Finalisé » imprimera entre « bonjour » et « au revoir ». Si vous créez un débogage (par exemple, CSC/debug GCTest.cs), "Finalized" sera imprimé après "bye" alors que le réglage x à null avant Collect() l'aurait "corrigé".

+0

Excellente analyse détaillée, merci Tony! –

+0

Downvote: ces gens recommandent tous le contraire en faveur de 'GC.Collect': [un Microsoft Distinguished Engineer] (http://blogs.msdn.com/b/cbrumme/archive/2003/04/16/51355. aspx), [l'équipe Visual Studio] (http://blogs.msdn.com/b/visualstudio/archive/2010/03/01/marshal-releasecomobject-considered-dangerous.aspx), et [un membre SO très bien classé ] (http://stackoverflow.com/a/17131389/1995977) –

+0

@Steve: Merci pour les liens. J'ai mis à jour la réponse pour inclure une référence à vos avertissements. –

Questions connexes