2009-12-17 12 views
6

Estoy mirando a través de una aplicación WPF en busca de una pérdida de memoria (utilizando ANTS Memory Profiler 5.1) y sigo viendo algunas páginas y controles que ocupan memoria cuando no deberían.¿Tengo una pérdida de memoria en mi WPF Navigation?

Así que ir al objeto de retención Gráfico y para ver lo que los está guardando alrededor, y seguir viendo esto para cada página:

Object Retention Graph http://img683.imageshack.us/img683/3013/ants.jpg

Lo que pasa es que tengo KeepAlive establece en false en cada página, y no creo que dicha propiedad exista en los controles del usuario.

¿Alguien me puede decir lo que debería estar buscando? ¿Esto es incluso una pérdida de memoria o es este comportamiento normal para una aplicación WPF?

Respuesta

8

Sí, según lo que ha proporcionado, tiene una pérdida de memoria. Cuando encuentre la cadena de referencias, y no esté en su código, la manera más fácil de hacerlo sería ... Reflector.

La imagen dice: JournalEntryKeepAlive._keepAliveRoot campo contiene una referencia al objeto. Vamos en Reflector y veamos cómo este tipo está enganchado con nuestro objeto.

Esta vez fue fácil, y todos los rastros conducen a la función NavigationService.MakeJournalEntry() y luego a NavigationService.IsContentKeepAlive(). Aquí está:

internal bool IsContentKeepAlive() 
{ 
    bool keepAlive = true; 
    DependencyObject dependencyObject = this._bp as DependencyObject; 
    if (dependencyObject != null) 
    { 
     keepAlive = JournalEntry.GetKeepAlive(dependencyObject); 
     if (!keepAlive) 
     { 
      PageFunctionBase base2 = dependencyObject as PageFunctionBase; 
      bool flag2 = !this.CanReloadFromUri; 
      if ((base2 == null) && flag2) 
      { 
       keepAlive = true; 
      } 
     } 
    } 
    return keepAlive; 
} 

Ya conoce las reglas. El objeto se mantiene en la memoria si:

  • No es un objeto de dependencia;
  • Propiedad adjunta JournalEntry.KeepAlive es verdadera;
  • No es una función de página y no se puede volver a cargar desde Uri.

Después de esta investigación, puede valer la pena leer más acerca de la propiedad JournalEntry.KeepAlive en MSDN.

Esta estrategia me ayudó a encontrar muchos insectos relacionados con la memoria. Espero que te ayude también :).

PD: Si sigue teniendo problemas para encontrar esta fuga en particular, puede pegar una muestra mínima de código para que la reproduzcamos y le proporcionemos una respuesta más adecuada.

Saludos, Anvaka

+0

Gracias por la explicación detallada, pero no estoy seguro de seguir la parte DependencyProperty. Si configuré KeepAlive como falso en todas las páginas, ¿por qué se mantendría en la memoria? – Brandon

+0

Siga la ruta lógica: incluso si establece KeepAlive = false en cada página, aún puede ser verdadero desde IsContentKeepAlive() cuando flag2 es verdadero, que dice:! CanReloadFromUri – Anvaka

+0

Ah, a la derecha. Gracias por la gran respuesta. – Brandon

5

que tenían el mismo problema y el mismo gráfico con el analizador de memoria hormigas. La aplicación utiliza una NavigationWindow para albergar algunos de WPF páginas y la navegación se hizo con este código subyacente:

NavigationService.Navigate(new Page1()); 

El problema fue creado por varias páginas mantienen en la memoria de la revista y que no pudieron ser basura recogida.

Lo que hice fue reemplazar el NavigationWindow con una ventana normal, las páginas con UserControls e intercambiar controles de usuario dentro de la ventana, como si fueran páginas. Hay muchos ejemplos sobre cómo hacer esto en google. Después de eliminar todas las llamadas a NavigationService.Navigate, finalmente podría juntar todas las páginas cerradas con Ants memory profiler.

+1

Inteligente. Pero mucho trabajo. Además, ¿no tendrías que desarrollar tu propio servicio de navegación? He intentado hacer eso, y es un verdadero dolor. – ouflak

+0

Sí, está construyendo un servicio de navegación propio. Sin embargo, es necesario debido a las pérdidas de memoria cuando se navega con '! This.CanReloadFromUri', es decir, como' Navigate (new Page()); '. – xmedeko