Windows 8.1 Hub App - Memory leak

Рейтинг: 0Ответов: 0Опубликовано: 22.09.2014

Здравствуйте.
Создаю пустой проект "Hub App".
Перехожу на любую другую страницу в этом проекте, возвращаюсь на главную страницу.
Далее делаю дамп памяти.
При анализе вижу

0:000> !loadby sos clr
0:000> !dumpheap -type Page
 Address       MT     Size
023b7870 0055715c       44     
023babd0 005556d4       40

Statistics:
      MT    Count    TotalSize Class Name
005556d4        1           40 App7.HubPage
0055715c        1           44 App7.ItemPage
Total 2 objects
0:000> !dumpheap -mt 0055715c
 Address       MT     Size
023b7870 0055715c       44

Statistics:
      MT    Count    TotalSize Class Name
0055715c        1           44 App7.ItemPage
Total 1 objects
0:000> !gcroot 023b7870 
HandleTable:
    00531904 (ref counted handle)
    -> 023b9e90 App7.Common.RelayCommand
    -> 023b9e50 System.Action
    -> 023b85bc App7.Common.NavigationHelper
    -> 023b7870 App7.ItemPage

    0053192c (ref counted handle)
    -> 023b7870 App7.ItemPage

Found 2 unique roots (run '!GCRoot -all' to see all roots).

Хочется понять, почему ItemPage по-прежнему живет в памяти?
Это нормальное поведение?

Заранее благодарен.


Для отключения "Cache" переходов в App.cs выставил rootFrame.CacheSize = 0; После этого ItemPage уничтожался. Но, при переходе в секцию и клике по тайлу, возвращаемся на главную страницу видим

HandleTable:
    002d1400 (ref counted handle)
    -> 02153410 App8.SectionPage

    002d140c (ref counted handle)
    -> 02154090 Windows.UI.Xaml.Controls.ItemClickEventHandler
    -> 02153410 App8.SectionPage

    002d1414 (ref counted handle)
    -> 0215453c App8.Common.NavigationHelper
    -> 02153410 App8.SectionPage
Found 3 unique roots (run '!GCRoot -all' to see all roots).

Посмотрев код вижу

public SectionPage()
{
    this.InitializeComponent();
    this.navigationHelper = new NavigationHelper(this);
    this.navigationHelper.LoadState += navigationHelper_LoadState;
}

Мы подписываемся на this.navigationHelper.LoadState но в коде нигде не отписываемся.

Поправив код

        public SectionPage()
        {
            this.InitializeComponent();
            this.navigationHelper = new NavigationHelper(this);
            this.navigationHelper.LoadState += navigationHelper_LoadState;

            Unloaded += OnUnloaded;
        }

        private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
        {
            this.navigationHelper.LoadState -= navigationHelper_LoadState;
        }

Добавил отписку от LoadState. Теперь ситуация в норме.

Странно что в приложении по умолчанию, то что рассчитано на показ как лучшая практика мы получаем не корректный код.

Спасибо

----------

Странно. Сейчас походил по страницам, покликал на тайлы и получил что на главной странице у меня в памяти осталось по нескольку экземпляров предыдущих страниц.

0:000> !dumpheap -type Page
 Address       MT     Size
02eb1914 0107716c       44     
02eb3bb0 01076b80       48     
02eba248 0107716c       44     
02ebc384 01076b80       48     
02ec1854 0107716c       44     
02ec3990 01076b80       48     
02ec8df8 0107716c       44     
02ecaf34 01076b80       48     
02ed045c 010756d4       40

Statistics:
      MT    Count    TotalSize Class Name
010756d4        1           40 App8.HubPage
0107716c        4          176 App8.ItemPage
01076b80        4          192 App8.SectionPage
Total 9 objects
0:000> !dumpheap -mt 0107716c
 Address       MT     Size
02eb1914 0107716c       44     
02eba248 0107716c       44     
02ec1854 0107716c       44     
02ec8df8 0107716c       44

Statistics:
      MT    Count    TotalSize Class Name
0107716c        4          176 App8.ItemPage
Total 4 objects
0:000> !gcroot 02eb1914
HandleTable:
    01051a2c (ref counted handle)
    -> 02eb3514 App8.Common.RelayCommand
    -> 02eb34d4 System.Action
    -> 02eb2038 App8.Common.NavigationHelper
    -> 02eb1914 App8.ItemPage

    01051a54 (ref counted handle)
    -> 02eb1914 App8.ItemPage

Found 2 unique roots (run '!GCRoot -all' to see all roots).

Почему это может происходить и куда можно смотреть дальше? Заранее благодарен.


Да, если в OnLoaded добавить

    GC.Collect();
    GC.WaitForPendingFinalizers();
    GC.Collect();

Мы получим всего две страницы, первая текущая, вторая это последняя страница на которую мы ходили. Вторая осталась по скольку OnLoaded отрабатывает раньше завершения работы предыдущей страницы.

0:000> !dumpheap -type Page
 Address       MT     Size
02730354 0087716c       44     
02730d28 008756e0       40

Statistics:
      MT    Count    TotalSize Class Name
008756e0        1           40 App10.HubPage
0087716c        1           44 App10.ItemPage
Total 2 objects

И того, получается утечки нет.

Буду рад выслушать предложения и замечания.

Спасибо

Ответы

Ответов пока нет.