- Jun 6, 2012
- 2
- 0
- 0
Hi,
I am developing one application in Silverlight for windows phone 7. I am stuck in very common issues which comes in windows phone app however not able to get out of it in any ways. It is memory leak issue which comes during navigation from first page to second, second to first and so on for multiple times.
To solve it, i create one new project having 2 blank pages. Each page has 2 text blocks to print current memory and peak memory and one button to move to next or previous page. When navigate from page 1 to page 2, i make null referance of all 3 things and call gc.collect to destroy the page referance. Same way, while moving from page 2 to page 1, i do the same thing.
I also tried to call gc.collect() in timer for every 500 mili seconds, but still no result. If i remove gc.collect() totally, memory increases in MB so i think it is a must thing.
Here is snippet of my code:
Main Page:
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();
}));
}
}
}
Second Page:
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();
}
}
}
}
Here is tracking of Current Memory which is increasing in each try:
Try Page 1 Page 2
1 74266048 7442432
2 6959104 8257536
3 6934528 8454144
4 8622080 8458240
5 8626176 8470528
6 8630272 8470528
Questions:
1) Is my flow and method proper for navigation from and back to manage memory?
2) Is my method to make referance null for text block and button is proper?
3) Also in my actual project, i am using databinding in listbox which i have destrcuted in following way.
if (listCountry != null)
{
listCountry.SelectionChanged -= listCountry_SelectionChanged;
//listCountry.Items.Clear();
listCountry.DataContext = null;
listCountry.ItemsSource = null;
listCountry.Resources.Clear();
listCountry.Resources = null;
listCountry = null;
}
I have doubt in this since in my project, there are multiple usage of such listbox.
Please take me out of this since i have spent lots of time in research and updates but not got the solution for current and peak memory.
Thanks in advance.
I am developing one application in Silverlight for windows phone 7. I am stuck in very common issues which comes in windows phone app however not able to get out of it in any ways. It is memory leak issue which comes during navigation from first page to second, second to first and so on for multiple times.
To solve it, i create one new project having 2 blank pages. Each page has 2 text blocks to print current memory and peak memory and one button to move to next or previous page. When navigate from page 1 to page 2, i make null referance of all 3 things and call gc.collect to destroy the page referance. Same way, while moving from page 2 to page 1, i do the same thing.
I also tried to call gc.collect() in timer for every 500 mili seconds, but still no result. If i remove gc.collect() totally, memory increases in MB so i think it is a must thing.
Here is snippet of my code:
Main Page:
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();
}));
}
}
}
Second Page:
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();
}
}
}
}
Here is tracking of Current Memory which is increasing in each try:
Try Page 1 Page 2
1 74266048 7442432
2 6959104 8257536
3 6934528 8454144
4 8622080 8458240
5 8626176 8470528
6 8630272 8470528
Questions:
1) Is my flow and method proper for navigation from and back to manage memory?
2) Is my method to make referance null for text block and button is proper?
3) Also in my actual project, i am using databinding in listbox which i have destrcuted in following way.
if (listCountry != null)
{
listCountry.SelectionChanged -= listCountry_SelectionChanged;
//listCountry.Items.Clear();
listCountry.DataContext = null;
listCountry.ItemsSource = null;
listCountry.Resources.Clear();
listCountry.Resources = null;
listCountry = null;
}
I have doubt in this since in my project, there are multiple usage of such listbox.
Please take me out of this since i have spent lots of time in research and updates but not got the solution for current and peak memory.
Thanks in advance.