2010-12-08 27 views
7

Dans le cas suivant:Pouvez-vous être bloqué en appelant GC.Collect et GC.WaitForPendingFinalizers?

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

La prise en compte des modes multi-threading et la collecte des ordures, dans quelles circonstances auriez-vous une impasse sur WaitForPendingFinalizers?

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

+2

Est-ce une question strictement préemptive, ou vous rencontrez une situation de blocage réel? (Si vous dépannez, il serait utile de publier le code pour votre (vos) méthode (s) de finalisation.) –

Répondre

6
// 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) 
     { 
      // ... 
     } 
    } 
} 
1

Il existe un fameux blocage sur WaitForPendingFinalizers, décrit par Jeffrey Richter. Il est montré ici: http://haacked.com/archive/2005/04/12/neverlockthis.aspx

 
class MyClass 
{ 

private bool isDisposed = false; 

    ~MyClass() 
    { 
     lock(this) 
     { 
      if(!isDisposed) 
      { 
       // ... 
      } 
     } 
    } 
} 
... 
MyClass instance = new MyClass(); 

Monitor.Enter(instance); 
instance = null; 

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

Il est causé par l'utilisation incorrecte de verrouillage (ce). Quoi qu'il en soit, c'est une situation où WaitForPendingFinalizers est verrouillé.

1

Vous ne rencontrerez aucune sorte de situation de blocage lors de l'appel GC.Collect et GC.WaitForPendingFinalizersà moins que vous accédez à des objets gérés dans vos Finalize méthodes. L'appel de méthodes d'autres objets avec une portée publique peut potentiellement conduire à des résultats imprévisibles, y compris un blocage. La raison en est que vous ne contrôlez pas totalement les schémas de verrouillage de ces autres objets. Il pourrait être verrouillé par n'importe qui pendant que votre méthode de finalisation tente d'y accéder.

En outre, le verrouillage this explicitement dans le finaliseur est presque garanti pour provoquer un blocage, comme le démontre la réponse de LukeH. Vous pouvez lire l'article original de Jeffrey Richter sur ce here. En règle générale, vous ne devez libérer que des ressources non gérées dans vos finaliseurs, ce qui devrait atténuer les problèmes liés aux blocages.

+0

En fait, il peut arriver que des objets finalisables contiennent des références à d'autres objets gérés. Par exemple, parce que les objets Bitmap sont chers, un programme qui doit stocker des centaines d'icônes 16x16 peut définir une classe qui alloue des bitmaps de 16x1024 pixels, chacun pouvant contenir 64 icônes, puis renvoyant des objets contenant chacun une référence. à un bitmap-allocator avec une indication de la partie qu'il «possède». Lorsqu'un tel objet 'bitmap piece' est éliminé, l'allocateur peut rendre cette partie du bitmap plus grande disponible à quelqu'un d'autre. – supercat

+0

Même si les seules références fortes au bitmap plus grand se trouvaient dans les objets 'bitmap piece', de sorte que l'abandon de tous ces objets rendrait la bitmap plus grande éligible à la finalisation, abandonnant tous les objets 'bitmap piece' sauf un associés à un bitmap laisserait le tout alloué mais la plupart du temps indisponible à d'autres fins. L'ajout d'un finaliseur à l'objet bitmap permettrait à l'objet maître de réutiliser des pièces abandonnées. Bien sûr, un tel code doit être écrit avec soin pour éviter les blocages ou autres problèmes d'enfilage, mais il peut toujours être utile. – supercat

+0

Je ne comprends pas ce que cela a à voir avec cette réponse ou question. @supercat –