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;
}
私のプロジェクトでは、そのようなリストボックスが複数回使用されているため、これには疑問があります。
研究と更新に多くの時間を費やしましたが、現在のメモリとピークメモリの解決策が得られていないため、これをやめてください。
前もって感謝します。デビッド・ジェイコブス。