2010-09-30 16 views
7

Tenemos una aplicación WPF, basada en Unity con el patrón MMVVVM. En el ciclo de vida de la aplicación puede haber varios ciclos de vida del proyecto, después de cada ciclo de vida del proyecto hacemos un Desgarre manual e intentamos liberar toda la referencia de ViewModels. Para suscripciones de eventos con Unity estamos utilizando referencias débiles. Así que estamos asumiendo que, después del derribo, podemos llamar a GC Collect, para que todos los objetos de basura sean recolectados. Tenemos otra opción para anular la suscripción manual de todos los eventos, pero preferimos la recolección de basura, ya que borrará alrededor de 200MB para nosotros, lo que facilitará la carga de nuevos proyectos.Bajo qué circunstancias, necesitamos llamar a GC.Colgar dos veces

Con una instancia, estamos observando que, si llamo a GC.Collect solo una vez, su referencia permanece en la memoria por algún tiempo.

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

Pero si intento llamar a GC dos veces seguidas, lo limpia todo muy bien.

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

Cualquier idea o sugerencia será muy apreciada.

Actualización:

No hay finalizadores definidos en la clase.

Ahora también estoy considerando un caso, en el que este objeto se refiere en otro objeto que podría tener un finalizador. En Nuestro marco, tenemos el finalizador solo para DBProvider, así que no creo, incluso este es el caso.

+5

¿Qué es MMVVVM? ¿La forma romana de codificación? – DanDan

+0

MVVM es común en WPF, pero en nuestro caso, tenemos varias aplicaciones diferentes en diferentes tecnologías .NET y todas están basadas en el framework DomainObject común. Así que decidimos una nueva capa MV sobre nuestros DomainObjects para facilitar nuestras aplicaciones WPF. –

+0

MMVVVM = 2985, creo. –

Respuesta

9

Parece que tiene algo con un finalizador, básicamente, si solo llama al GC.Collect() una vez, los finalizadores están finalizando pero los objetos finalizados no se están recogiendo.

Si eso representa o no un error es una cuestión diferente. En general, no es una buena idea que haya finalizadores que realmente deban ejecutarse, pero quizás esté bien en su caso.

+0

Comprobé con esa clase en particular, hasta donde puedo ver, no hay finalizadores. –

+0

Ahora estoy considerando un caso, en el que este objeto se refiere a otro objeto que podría tener un finalizador. –

+0

Si cualquier objeto tiene un finalizador, cualquier objeto al que tenga referencias directas o indirectas sobrevivirá al menos parcialmente al siguiente GC (los finalizadores, si los hay, se ejecutarán en dichos objetos; WeakReferences puede sobrevivir, pero no confiaría en que siempre lo hará). – supercat

6

Si llamo a GC.Collect solo una vez, su referencia permanece en la memoria por algún tiempo.

No es realmente extraño. Cuando un objeto tiene un Finalizador (y no se ha llamado a GC.SuppressFinalize() en él), obtiene una suspensión de la ejecución (es no recopilado, por lo que el finalizador puede ejecutarse con objetos válidos). Todas las instancias a las que hace referencia este objeto también obtienen una suspensión de la ejecución. Se necesita una segunda ronda a través del GC para limpiarlo todo.

Por otro lado, la mayoría de los programas, incluidos los grandes y complejos, deberían poder ejecutarse sin llamar a GC.Collect() ni siquiera una vez. Y al que desea llamar dos veces ...

después de cada ciclo de vida del proyecto que hacemos un manual derribar

suena complicado y fáciles de evitar ... ¿Cuántas hay refernces en su dominio/Ver modelos? Lo ideal sería cortar 1 o 2 referencias a un objeto "principal" y olvidarse de él.

+0

En realidad, los objetos del proyecto entero se encuentran en la memoria, incluidos V MV MV y M para Project life cycle, por lo que decidimos hacer una rotura manual También considero el caso mencionado por usted, por favor vea los comentarios sobre la respuesta de Jon Skeet. –

+0

Todavía no veo la necesidad de un derribo manual, pero será complejo y solo necesitará perder una pequeña referencia. . –

0

@Nitin, no estoy seguro de si mi sugerencia podría ser útil o no, pero como regla general debemos evitar llamar explícitamente a GC.Collect(). porque es probable que cause un problema de rendimiento.En cambio, trate de seguir el patrón de eliminación adecuado.

0

Tiene una referencia débil que espera que se establezca como nula, como llama a GC y cree que nada mantiene vivo el objeto.

No sé cómo se implementan las referencias débiles en .net, pero es muy posible que retrasen la recolección de objetos y hagan uso de un sistema como los finalizadores.

O podría ser que tenga un objeto que debe estar finalizado, ya que no ha llamado a disponer() sobre él. (Muy común con WPF o WinForms)

Para averiguarlo, necesita usar un MemoryProfiler, espere pasar al menos un día apoyándose en cómo usar cualquier generador de perfiles de memoria, ya que se le presentarán muchos datos sobre objetos interno a WPF. Personalmente, me gustaría descargar un rastro libre de Redgate’s memory profiler y probar el problema, la ayuda también es útil. (Otros perfiladores de memoria también funcionan bien, en gran medida solo depende de a qué esté acostumbrado).

Cuestiones relacionadas