2012-07-04 2 views
1

Windows Phone 7 용 Silverlight에서 하나의 응용 프로그램을 개발 중입니다. Windows 전화 응용 프로그램에서는 제공되지만 어떤 방식 으로든 벗어날 수없는 매우 일반적인 문제에 빠져 있습니다. 첫 페이지에서 두 번째로, 네 번째에서 네 번째로 네비게이션하는 동안 여러 번 메모리 누출 문제가 발생합니다.WP7 탐색 - 목록 상자 바인딩의 WP7 메모리 누수 문제

해결하려면 두 개의 빈 페이지가있는 새 프로젝트를 하나 만듭니다. 각 페이지에는 현재 메모리 및 피크 메모리를 인쇄하는 2 개의 텍스트 블록과 다음 또는 이전 페이지로 이동하는 하나의 버튼이 있습니다. 페이지 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(); 
       })); 
      } 
     } 
    } 

두 번째 페이지 :

메인 페이지 : 여기

내 코드의 조각입니다

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) 또한 내 실제 프로젝트에서 나는 listbox에서 데이터 바인딩을 사용하고 있는데, 나는 다음과 같은 방식으로 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; 
    } 

내 프로젝트에는이 목록 상자가 여러 번 사용되기 때문에 의심 스럽습니다.

나는 연구와 업데이트에서 많은 시간을 보냈지 만 현재와 최고 메모리에 대한 해결책을 얻지 못했기 때문에 나를 빼 버려주세요.

미리 감사드립니다. David Jacobs.

+0

샘플에 링크를 추가하십시오. 아무도 자신의 PC를 다시 작성할 수 없으므로 –

+0

Alex입니다. 이것은 내 PC의 데모 프로젝트입니다. 두 페이지의 코드를 모두 넣었습니다. –

+0

이 누출은 WP7의 탐색 서비스의 정상적인 동작 일 수 있습니다. 이것을 확인하려면 p1 -> p2 -> p1에서 탐색하여 시나리오를 재현 한 다음 p2로 돌아온 다음 p1 –

답변

1

WP8 앱을 개발하는 동안 동일한 문제가있었습니다. 두 번째 페이지에서 정확히 OnBackKeyPress 메서드를 재정의 할 때는 스택 (또는 JournalEntry)에서 페이지를 제거해야합니다. 그렇지 않으면 스택에 남겨두기 때문에 페이지를 GC로 가져올 수 없기 때문에 페이지를 스택에서 제거해야합니다 (또는 JournalEntry). OnBackKeyPress 방법에 NavigationService.RemoveBackEntry();을 추가해야하며 먼저 NavigationService.RemoveBackEntry();에 전화를 걸어 원하는 것을하십시오.