1

Windows Phone 7 用の Silverlight で 1 つのアプリケーションを開発しています。これは、最初のページから 2 番目のページへ、2 番目のページから最初のページへ、というように複数回移動するときに発生するメモリ リークの問題です。

それを解決するために、2 つの空白ページを持つ新しいプロジェクトを 1 つ作成します。各ページには、現在のメモリとピーク メモリを印刷するための 2 つのテキスト ブロックと、次または前のページに移動するための 1 つのボタンがあります。ページ 1 からページ 2 に移動するとき、3 つすべてを null 参照し、gc.collect を呼び出してページ参照を破棄します。同じように、ページ 2 からページ 1 に移動しながら、同じことを行います。

また、タイマーで 500 ミリ秒ごとに gc.collect() を呼び出そうとしましたが、まだ結果はありません。gc.collect() を完全に削除すると、メモリが MB 単位で増加するので、必須だと思います。

ここに私のコードのスニペットがあります:

メインページ:

    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();
                }));
            }
        }
    }

2 ページ目:

    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();
                }
            }
        }
    }

各試行で増加している現在のメモリの追跡は次のとおりです。

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

質問: 1) フローとメソッドは、メモリを管理するためのナビゲーションに適していますか? 2) テキスト ブロックとボタンの参照を null にする方法は適切ですか? 3)実際のプロジェクトでも、リストボックスでデータバインディングを使用していますが、これは次の方法でdestrcutedしています。

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

私のプロジェクトでは、そのようなリストボックスが複数回使用されているため、これには疑問があります。

研究と更新に多くの時間を費やしましたが、現在のメモリとピークメモリの解決策が得られていないため、これをやめてください。

前もって感謝します。デビッド・ジェイコブス。

4

1 に答える 1

1

WP8アプリの開発中に同じ問題が発生しました。メソッドをオーバーライドする場合OnBackKeyPress、正確には 2 ページ目で、ページをスタック (または) から削除する必要があります。そうしないと、ページをスタックJournalEntryに残したままにし、GC で取得できないためです。NavigationService.RemoveBackEntry();メソッドに追加する必要があります。OnBackKeyPress最初に呼び出しNavigationService.RemoveBackEntry();てから、必要なことを行うことが重要です。

于 2013-04-30T13:55:04.193 に答える