Problema de pérdida de memoria WP7 en la navegación: enlace de cuadro de lista

Estoy desarrollando una aplicación en Silverlight para Windows Phone 7. Estoy atascado en problemas muy comunes que vienen en la aplicación de Windows Phone, pero no puedo salir de ella de ninguna manera. Es un problema de fuga de memoria que surge durante la navegación de la primera página a la segunda, de la segunda a la primera y así sucesivamente varias veces.

Para resolverlo, creo un nuevo proyecto que tiene 2 páginas en blanco. Cada página tiene 2 bloques de texto para imprimir la memoria actual y la memoria máxima y un botón para pasar a la página siguiente o anterior. Cuando navego de la página 1 a la página 2, hago una referencia nula de las 3 cosas y llamo a gc.collect para destruir la referencia de la página. De la misma manera, al pasar de la página 2 a la página 1, hago lo mismo.

También traté de llamar a gc.collect() en el temporizador cada 500 milisegundos, pero aún no obtuve ningún resultado. Si elimino gc.collect() por completo, la memoria aumenta en MB, por lo que creo que es algo imprescindible.

Aquí hay un fragmento de mi código:

Página principal:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Controls;
    using Microsoft.Phone.Controls;
    using System.Windows.Threading;

    namespace AppMemory
    {
        public partial class MainPage : PhoneApplicationPage
        {

            // Constructor
            public MainPage()
            {
                InitializeComponent();

                txtCM.Text = "C : " + Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage.ToString();
                txtPM.Text = "P: " + Microsoft.Phone.Info.DeviceStatus.ApplicationPeakMemoryUsage.ToString();
            }

            // Simple button Click event handler to take us to the second page
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
            }

            protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
            {
                while (this.NavigationService.BackStack.Any())
                {
                    this.NavigationService.RemoveBackEntry();
                }
            }

            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                while (this.NavigationService.BackStack.Any())
                {
                    this.NavigationService.RemoveBackEntry();
                }
            }
            protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
            {
                dosposeMemory();
                base.OnNavigatedFrom(e);
                this.DataContext = null;
                GC.Collect();
            }

            public void dosposeMemory()
            {
                try
                {
                    if (txtCM != null)
                    {
                        txtCM.Text = null;
                        txtCM = null;
                    }

                    if (txtPM != null)
                    {
                        txtPM.Text = null;
                        txtPM = null;
                    }

                    if (btn1 != null)
                    {
                        btn1.Click -= Button_Click;
                        btn1.Style = null;
                        btn1.Resources.Clear();
                        btn1.Resources = null;
                        btn1 = null;
                    }

                    if (ContentPanel != null)
                    {
                        ContentPanel.Children.Clear();
                        ContentPanel.Resources.Clear();
                        ContentPanel.Resources = null;
                        ContentPanel = null;
                    }

                    if (LayoutRoot != null)
                    {
                        LayoutRoot.DataContext = null;
                        LayoutRoot.Background = null;
                        LayoutRoot.Resources.Clear();
                        LayoutRoot.Resources = null;
                        LayoutRoot.Children.Clear();
                        LayoutRoot = null;
                    }

                  if (app1 != null)
                    {
                        app1.Resources.Clear();
                        app1.Resources = null;
                        app1 = null;
                    }

                    GC.Collect();
                }
                catch(Exception)
                {

                }
            }

            ~MainPage()
            {
                System.Windows.Deployment.Current.Dispatcher.BeginInvoke(new System.Action(() =>
                {
                    GC.Collect();
                }));
            }
        }
    }

Segunda pagina:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using Microsoft.Phone.Controls;

    namespace AppMemory
    {
        public partial class Page1 : PhoneApplicationPage
        {
            public Page1()
            {
                InitializeComponent();
                textBlock1.Text = "C : " + Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage.ToString();
                textBlock2.Text = "P: " + Microsoft.Phone.Info.DeviceStatus.ApplicationPeakMemoryUsage.ToString();
            }
            protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
            {
                while (this.NavigationService.BackStack.Any())
                {
                    this.NavigationService.RemoveBackEntry();
                }

                NavigationService.Navigate(new Uri("/MainPage.xaml", UriKind.Relative));
            }
            protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
            {
                while (this.NavigationService.BackStack.Any())
                {
                    this.NavigationService.RemoveBackEntry();
                }
            }
            protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
            {
                dosposeMemory();
                base.OnNavigatedFrom(e);
                this.DataContext = null;
                GC.Collect();
            }
            public void dosposeMemory()
            {
                try
                {
                    if (textBlock1 != null)
                    {
                        textBlock1.Text = null;
                        textBlock1 = null;
                    }

                    if (textBlock2 != null)
                    {
                        textBlock2.Text = null;
                        textBlock2 = null;
                    }

                    if (ContentPanel != null)
                    {
                        ContentPanel.Children.Clear();
                        ContentPanel.Resources.Clear();
                        ContentPanel.Resources = null;

                        ContentPanel = null;
                    }
                    if (LayoutRoot != null)
                    {
                        LayoutRoot.Children.Clear();
                        LayoutRoot.Resources.Clear();
                        LayoutRoot.Resources = null;

                        LayoutRoot = null;
                    }
                    if (page1 != null)
                    {
                        page1.Resources.Clear();
                        page1.Resources = null;
                        page1 = null;
                    }
                    GC.Collect();
                }
                catch (Exception)
                {
                    GC.Collect();
                }
            }
        }
    }

Aquí está el seguimiento de la memoria actual que aumenta en cada intento:

    Try Page 1      Page 2
    1   7426048         7442432
    2   6959104     8257536
    3   6934528     8454144
    4   8622080     8458240
    5   8626176     8470528
    6   8630272     8470528

Preguntas: 1) ¿Mi flujo y método son adecuados para navegar desde y hacia atrás para administrar la memoria? 2) ¿Es correcto mi método para hacer que la referencia sea nula para el bloque de texto y el botón? 3) También en mi proyecto real, estoy usando el enlace de datos en el cuadro de lista que he destruido de la siguiente manera.

    if (listCountry != null)
    {
        listCountry.SelectionChanged -= listCountry_SelectionChanged;
        //listCountry.Items.Clear();
        listCountry.DataContext = null;
        listCountry.ItemsSource = null;
        listCountry.Resources.Clear();
        listCountry.Resources = null;
        listCountry = null;
    }

Tengo dudas sobre esto ya que en mi proyecto hay múltiples usos de dicho cuadro de lista.

Sáquenme de esto, ya que pasé mucho tiempo investigando y actualizando, pero no obtuve la solución para la memoria actual y máxima.

Gracias por adelantado. David Jacobs.

preguntado el 04 de julio de 12 a las 07:07

Por favor, agregue un enlace a la muestra, para que cualquiera pueda reproducir en su propia PC -

Alex, este es un proyecto de demostración en mi PC. He puesto el código de ambas páginas. -

Esta fuga podría ser un comportamiento normal del servicio de navegación en WP7. Para verificar esto, reproduzca el escenario con navegación desde p1 -> p2 -> p1 y luego regrese a p2 y luego regrese a p1 -

y esto es incómodo listCountry.Resources.Clear(); listCountry.Resources = null; -

Hola alex.. sí, eso pensé. No tengo claro la destrucción del cuadro de lista con el enlace de datos. ¿Puedes por favor guiarme para esto? -

1 Respuestas

Tuve el mismo problema al desarrollar la aplicación WP8. Cuando anulas el OnBackKeyPress método, en su segunda página para ser precisos, debe eliminar la página de la pila (o JournalEntry) porque, si no lo hace, lo deja en la pila y GC no puede recogerlo. Necesitas agregar NavigationService.RemoveBackEntry(); En el correo electrónico “Su Cuenta de Usuario en su Nuevo Sistema XNUMXCX”. OnBackKeyPress método y es importante primero llamar NavigationService.RemoveBackEntry(); y luego haz lo que quieras.

Respondido 30 Abr '13, 14:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.