2010-04-27 11 views
2

J'ai écrit une classe managée qui entoure un objet C++ non managé, mais j'ai trouvé que - en l'utilisant en C# - le GC démarre tôt alors que j'exécute une méthode sur L'object. J'ai lu sur la collecte des ordures et comment l'empêcher de se produire tôt. Une façon consiste à utiliser une instruction "using" pour contrôler quand l'objet est éliminé, mais cela met la responsabilité sur le client de l'objet géré. Je pourrais ajouter à la classe gérée:Meilleure façon d'empêcher la récupération de place rapide dans CLR

MyManagedObject::MyMethod() {

System::Runtime::InteropServices::GCHandle handle = 
    System::Runtime::InteropServices::GCHandle::Alloc(this); 

// access unmanaged member 

handle.Free(); 

}

Cela semble fonctionner. Étant nouveau à .NET, comment les autres personnes font face à ce problème?

Merci,

Johan

+1

le GC ne donnera pas de coup de pied si quelque chose a une référence à votre objet .... Je pense que quelque chose d'autre peut se produire avec votre code original. –

+0

À quoi ressemble le code C# utilisant cet objet? –

+0

Je lis cet article: http://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx Si je fais: MyManagedObject obj = new MyManagedObject(); obj.MonMethod(); Alors obj peut être (et est dans mon cas) garbage collecté pendant l'exécution de MyMethod, à moins que le compilateur puisse détecter que MyMethod accède aux membres de MyManagedObject. Malheureusement, MyMethod accède simplement au code non managé dans mon cas, donc le GC l'ignore heureusement et élimine mon objet lors de l'exécution de MyMethod. – Johan

Répondre

1

Vous pouvez utiliser GC.KeepAlive(this) dans le corps de votre méthode si vous voulez garder le finaliseur d'être appelé. Comme d'autres l'ont noté correctement dans les commentaires, si votre référence this n'est pas active pendant l'appel de la méthode, il est possible que le finaliseur soit appelé et que la mémoire soit récupérée pendant l'appel. Pour une étude de cas détaillée, voir http://blogs.microsoft.co.il/blogs/sasha/archive/2008/07/28/finalizer-vs-application-a-race-condition-from-hell.aspx.

3

Vous pouvez jeter un oeil à cet article: http://www.codeproject.com/Tips/246372/Premature-NET-garbage-collection-or-Dude-wheres-my. Je crois que cela décrit exactement votre situation. En bref, les remèdes sont un bloc using ou un GC.KeepAlive. Cependant, je suis d'accord que dans de nombreux cas, vous ne voudrez pas transmettre ce fardeau au client de l'objet non géré; dans ce cas, un appel à GC.KeepAlive (this) à la fin de chaque méthode wrapper est une bonne solution.