2010-04-20 10 views
12

Tengo un objeto, que I cree que solo lo tiene WeakReference. He rastreado sus titulares de referencia usando SOS y SOSEX, y ambos confirman que este es el caso (no soy un experto en SOS, así que podría estar equivocado en este punto).¿Cómo decide el recolector de basura cuándo matar los objetos mantenidos por WeakReferences?

La explicación estándar de WeakReferences es que el GC las ignora al hacer sus barridos. No obstante, mi objeto sobrevive a una invocación a GC.Collect (GC.MaxGeneration, GCCollectionMode.Forced).

¿Es posible que un objeto al que solo se hace referencia con WeakReference sobreviva a esa colección? ¿Hay una colección aún más completa que pueda forzar? O, ¿debería volver a visitar mi creencia de que las únicas referencias al objeto son débiles?

actualización y conclusión causa

La raíz era que había una referencia en la pila que estaba bloqueando el objeto. No está claro por qué ni SOS ni SOSEX estaban mostrando esa referencia. El error del usuario siempre es una posibilidad.

En el curso del diagnóstico de la causa raíz, realicé varios experimentos que demostraron que las WeakReferences para objetos de 2ª generación pueden permanecer durante un tiempo sorprendentemente largo. Sin embargo, un objeto de segundo gen WRd no sobrevivirá a sobre GC.Collect (GC.MaxGeneration, GCCollectionMode.Forced).

+0

Objetos _aren't_ en poder de WeakReferences. Ese es precisamente su punto. Es probable que haya algo más que los mantenga vivos. – zneak

+0

¿Qué sucede cuando llamas a GC.GetGeneration (yourWeakReference)?¿Devuelve algo o arroja una excepción? – MusiGenesis

+0

¿Qué muestra! Gchandles y! Gcroot show? –

Respuesta

0

Según Wikipedia "Un objeto referenciado solamente por referencias débiles se considera inalcanzable (o 'débilmente accesible') y así se pueden recoger en cualquier momento. Referencias débiles se utilizan para evitar mantener referencia a memoria por objetos que no sean necesarios"

No estoy seguro de si su caso es sobre referencias débiles ...

+1

Conozco muy bien la descripción estándar de las referencias débiles. Mi caso se trata de reexaminar la descripción estándar de las referencias débiles porque actualmente estoy confrontado con evidencia que sugiere que el comportamiento real es más sofisticado. –

0

Intente llamar GC.WaitForPendingFinalizers() inmediatamente después de GC.Collect().

Otra opción posible: nunca use un WeakReference para ningún propósito. En la naturaleza, solo los he visto usar como un mecanismo para reducir la huella de memoria de una aplicación (es decir, una forma de almacenamiento en caché). A medida que el poderoso MSDN dice:

Evitar el uso de referencias débiles como una solución automática a los problemas de gestión de memoria . En su lugar, desarrolle una política de caché efectiva para manejando los objetos de su aplicación.

+0

Tengo WaitForPendingFinalizers en mi código. En general, estoy de acuerdo con usted en que el 99% del tiempo si usa WR, lo está haciendo mal. Creo que este es el caso del 1%. Tengo que mantener una lista central de objetos que no afecte la duración del objeto. –

+0

La mayoría de las veces, cuando 'Foo' contiene una referencia a' Bar', lo hará porque "necesita" 'Bar'. En algunas ocasiones, sin embargo, 'Foo' puede contener una referencia a' Bar' solo para que pueda hacer cosas * en beneficio de otros objetos que necesitan 'Bar' *. Si no hay otros objetos que necesiten una barra, 'Foo' tan pronto como' Bar', y la referencia a la misma, se reemplazará con una indicación de que ya no necesita servirla. – supercat

+0

@supercat en su último caso, lo que se debe usar en .NET 4+ no es WeakReference, sino [ConditionalWeakTable] (http://msdn.microsoft.com/en-us/library/dd287757.aspx). –

0

Le recomiendo que compruebe las "otras" referencias a los objetos débilmente referenciados. Porque, si todavía hay otra referencia viva, los objetos no serán GCed.

+1

Esto ya se ha mencionado. –

0

Objetos débilmente referenciados do eliminados por la recolección de basura. He tenido el placer de depurar sistemas de eventos donde no se disparaban los eventos ... Resultó ser porque el suscriptor solo tenía una referencia débil y, por lo tanto, después de un eventual retraso aleatorio, el GC eventualmente lo recolectaría. En ese momento, la UI dejó de actualizarse. :)

Cuestiones relacionadas