Pouvez-vous bloquer les appels sur GC.Collect et GC.WaitForPendingFinalizers?

Compte tenu de ce qui suit:

GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); GC.Collect(GC.MaxGeneration); 

Compte tenu des modes WaitForPendingFinalizers de WaitForPendingFinalizers , dans quelles circonstances obtiendriez-vous un blocage sur WaitForPendingFinalizers ?

Remarque: je ne cherche pas de réponses sur les raisons pour lesquelles vous ne devriez pas appeler GC.Collect .

 // causes a deadlock when built with release config and no debugger attached // building in debug mode and/or attaching the debugger might keep // badIdea alive for longer, in which case you won't see the deadlock // unless you explicitly set badIdea to null after calling Monitor.Enter var badIdea = new BadIdea(); Monitor.Enter(badIdea); GC.Collect(GC.MaxGeneration); GC.WaitForPendingFinalizers(); GC.Collect(GC.MaxGeneration); // ... public class BadIdea { ~BadIdea() { lock (this) { // ... } } } 

Il y a une impasse célèbre sur WaitForPendingFinalizers, décrite par Jeffrey Richter. Il est montré ici: http://haacked.com/archive/2005/04/12/neverlockthis.aspx

 classe MyClass
 {

 private bool isDisposed = false;

     ~ MyClass ()
     {
         verrouiller
         {
             si (! isDisposed)
             {
                 // ...
             }
         }
     }
 }
 ...
 MyClass instance = new MyClass ();

 Monitor.Enter (instance);
 instance = null;

 GC.Collect ();
 GC.WaitForPendingFinalizers ();

Cela est dû à une utilisation incorrecte du verrou (this). Quoi qu’il en soit, il s’agit d’une situation où WaitForPendingFinalizers est verrouillé.

Lorsque vous appelez GC.Collect et GC.WaitForPendingFinalizers vous ne rencontrerez aucune impasse, sauf si vous GC.WaitForPendingFinalizers à des objects gérés dans vos méthodes Finalize . L’appel de méthodes d’autres objects avec une étendue publique peut potentiellement conduire à des résultats imprévisibles, y compris une impasse. La raison en est que vous ne contrôlez pas totalement les schémas de locking de ces autres objects. Cela pourrait être verrouillé par n’importe qui pendant que votre méthode de finalisation tente d’y accéder.

De plus, le locking explicite de this dans le finaliseur est presque garanti , comme le montre la réponse de LukeH. Vous pouvez lire l’article original de Jeffrey Richter à ce sujet ici .

En général, vous ne devez libérer que des ressources non gérées dans vos finaliseurs, ce qui devrait dissiper les inquiétudes de ce type concernant les blocages.