Windows 8.1 Hub App - Memory leak
Здравствуйте.
Создаю пустой проект "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
И того, получается утечки нет.
Буду рад выслушать предложения и замечания.
Спасибо