2010-04-20 10 views
12

Ho un oggetto, che avviso è mantenuto da un WeakReference. Ho rintracciato i suoi referenti usando SOS e SOSEX, ed entrambi confermano che questo è il caso (non sono un esperto SOS, quindi potrei sbagliarmi su questo punto).In che modo il Garbage Collector decide quando uccidere oggetti tenuti da WeakReferences?

La spiegazione standard WeakReferences è che il GC li ignora quando si fa i suoi spazza. Tuttavia, il mio oggetto sopravvive a una chiamata a GC.Collect (GC.MaxGeneration, GCCollectionMode.Forced).

E 'possibile per un oggetto a cui fa riferimento solo con un WeakReference per sopravvivere che la raccolta? C'è una collezione ancora più completa che posso forzare? Oppure, dovrei rivedere la mia convinzione che gli unici riferimenti all'oggetto sono deboli?

Update e Conclusione causa

La radice era che c'era un riferimento in pila che stava chiudendo l'oggetto. Non è chiaro il motivo per cui né SOS né SOSEX hanno mostrato tale riferimento. L'errore dell'utente è sempre una possibilità.

Nel corso della diagnosi della causa principale, ho fatto diversi esperimenti che hanno dimostrato che le WeakReferences per oggetti di seconda generazione possono rimanere intorno a un tempo sorprendentemente lungo. Tuttavia, un oggetto WRd 2nd gen non sarà valido per GC.Collect (GC.MaxGeneration, GCCollectionMode.Forced).

+0

Gli oggetti non sono registrati da WeakReferences. Questo è esattamente il loro punto. Probabilmente c'è qualcos'altro che li tiene in vita. – zneak

+0

Cosa succede quando chiami GC.GetGeneration (yourWeakReference)?Restituisce qualcosa o genera un'eccezione? – MusiGenesis

+0

Cosa mostra! Gchandles e! Gcroot mostra? –

risposta

0

Secondo wikipedia "Un oggetto fa riferimento solo ai riferimenti deboli è considerato irraggiungibile (o 'debolmente raggiungibile') e quindi possono essere raccolte in qualsiasi momento. I riferimenti deboli vengono utilizzati per evitare di mantenere riferimento memoria da oggetti non necessari"

Non sono sicuro che il tuo caso riguardi riferimenti deboli ...

+1

Sono ben consapevole della descrizione standard dei riferimenti deboli. Il mio caso riguarda la riesame della descrizione standard dei riferimenti deboli perché attualmente mi trovo di fronte a prove che suggeriscono che il comportamento reale è più sofisticato. –

0

Prova a chiamare GC.WaitForPendingFinalizers() subito dopo GC.Collect().

Un'altra possibile opzione: Non utilizzare mai un WeakReference per qualsiasi scopo. In natura, li ho sempre visti solo come meccanismo per ridurre l'impronta di memoria di un'applicazione (ad esempio una forma di memorizzazione nella cache). Come il potente MSDN dice:

Evitare di utilizzare riferimenti deboli come una soluzione automatica alla memoria problemi di gestione. Al contrario, sviluppa un criterio di caching efficace per che gestisce gli oggetti dell'applicazione.

+0

Ho WaitForPendingFinalizers nel mio codice. Sono generalmente d'accordo con te sul fatto che il 99% delle volte se usi la WR, stai sbagliando. Penso che questo sia il caso dell'1%. Devo mantenere una lista centrale di oggetti che non influisce sulla durata dell'oggetto. –

+0

La maggior parte delle volte, quando "Foo" contiene un riferimento a "Bar", lo farà perché "ha bisogno" di "Barra". In alcune occasioni, tuttavia, "Foo" può mantenere un riferimento a "Bar" puramente in modo che possa fare cose * a beneficio di altri oggetti che hanno bisogno di "Bar" *. Se non ci sono altri oggetti che necessitano di una barra, 'Foo' dovrebbe avere" Bar "e il riferimento ad esso, sostituito dall'indicazione che non è più necessario servirlo. – supercat

+0

@supercat in quest'ultimo caso, la cosa da utilizzare in .NET 4+ non è WeakReference, ma [ConditionalWeakTable] (http://msdn.microsoft.com/en-us/library/dd287757.aspx). –

0

Si consiglia di verificare gli "altri" riferimenti agli oggetti debolmente referenziati. Perché se c'è un altro riferimento ancora vivo, gli oggetti non saranno sottoposti a GC.

+1

Questo è già stato menzionato. –

0

Gli oggetti debolmente referenziati do vengono rimossi dalla procedura di garbage collection. Ho avuto il piacere di eseguire il debug di sistemi di eventi in cui gli eventi non venivano sparati ... Si è scoperto perché l'abbonato era solo debolmente referenziato e quindi dopo un certo ritardo casuale il GC alla fine lo avrebbe raccolto. A quel punto l'interfaccia utente ha smesso di aggiornare. :)

Problemi correlati