Я столкнулся с очевидной утечкой памяти в приложении, которое открывало окно настроек, содержащее TabControl с несколькими TabItems. Первоначально полагая, что один из показанных пользовательских элементов управления должен быть виновником, я закомментировал кучу вещей, наконец вытащил JetBrains dotMemory и создал демо-программу.
Проблема (я думаю)
Когда Window содержит TabControl с хотя бы одним TabItem, когда окно закрыто, Window-объект все еще существует. Если в TabControl нет TabItems, объект Window уничтожается немедленно (как и ожидалось).
Сохранение
В соответствии с dotMemory, 'Retention' происходит из WindowAutomationPeer (._owner), из TabControlAutomationPeer (._ parent), из TabItemAutomationPeer (._ parent), из ElementProxy (._ peer), а затем в нижней части появляется надпись «RefCounting handle».
Воспроизведение
Создание нового C# WPF-приложения (Целевая среда:. NET Framework 4.7.2) с именем "TabsIn Windows"
Добавление кнопки в MainWindow:
<Window x:Class="TabsInWindows.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<Grid>
<Button Content="Open tab window" Click="Button_Click"/>
</Grid>
</Window>
Создайте новое окно, «TabsWindow» с TabControl и TabItem:
<Window x:Class="TabsInWindows.TabsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="TabsWindow" Height="200" Width="300">
<Grid>
<TabControl x:Name="Subject">
<TabItem></TabItem>
</TabControl>
</Grid>
</Window>
Сделайте кнопку в MainWindow открытым новым TabWindow
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//TabsWindow.Open(this);
TabsWindow w = new TabsWindow();
w.Show();
}
}
Запустите применение. Каждый раз, когда вы нажимаете кнопку, создается новое окно, но TabItem (?) И, следовательно, TabWindow остаются при закрытии окна. (Повторите любое количество раз)
Как исправить?
Моя проблема заключается в том, что в моем реальном приложении все содержимое всех вкладок, похоже, сохраняется в памяти, вызывая значительная утечка памяти.
В демонстрационном приложении я попытался сделать несколько вещей, чтобы избежать зависания объектов; Установка содержимого Grid на ноль. Очистка элементов в TabControl (Тема). Очистка детей от решетки. Ничего из этого не сработало.
Я не могу понять, что такое объекты 'AutomationPeer' или для чего создан ElementProxy и почему он не будет d ie.
Если кто-нибудь может рассказать мне, как обойти эту проблему, или может пролить некоторый свет на то, что такое ElementProxy и почему он торчит, было бы очень полезно.
Во время написания этого я сделал продолжайте работу dotMemory с тестовым приложением, и через некоторое время после того, как что-то будет сделано в последний раз, объекты действительно будут удалены ...
В связи с этим возникает вопрос: как долго можно ожидать, что объект станет видимым? в памяти, со ссылками, до того, как он будет удален?
В реальном проекте
Затем я попробовал нечто подобное в реальном проекте, гарантируя, что не наши собственные элементы управления были напрямую связаны с SettingsWindow (я не исключаю, что у меня возникла проблема с памятью / ссылкой в одном из наших элементов управления, поэтому все элементы управления, перечисленные непосредственно в «Пути хранения ключей», были закомментированы). У меня осталось «3 уникальных ветви», одна из которых является «EffectiveValueEntry [40]» из собственного расширения ListBox, две другие - «EffectiveValueEntry» ([19] и [22] соответственно), оба из TextBlock, из TextBlockAutomationPeer [4], List, ListBoxItemAutomationPeer, ElementProxy.
После примерно десяти минут бездействия окно настроек все еще там, но изменились «Пути сохранения ключа», и «20 уникальных ветвей» все EffectiveValueEntry ([32] на первом, [42] на остальных), TextBox, TextEditor, но теперь «F-Reachable Queue» находится внизу списка.
Еще через десять минут, окно «Настройки» окончательно исчезло.
Затем я снова открыл окно настроек несколько раз, и через минуту после закрытия последнего остались только ссылки «TextBox», которые были оставлены, и принудительная сборка мусора позже (с помощью кнопки в dotMemory) ссылки на объекты исчезли.
Во что верить?
Так что, очевидно, если я буду долго ждать будет достаточно «волхвов c» - но это компьютер, а не волшебный c -box!
Может ли кто-нибудь объяснить мне, почему некоторые объекты будут появляться в памяти дольше, но в конечном итоге будут удалены? Как долго следует ожидать, что такие объекты будут лежать?
Я бы также хотел, чтобы эти объекты-призраки не использовались в TabItems, у них не должно быть причин занимать память, если они в конечном итоге будут в любом случае удалено ... Видите ли, я обнаружил это во время тестирования производительности некоторых компонентов пользовательского интерфейса в окне настроек, и повторные тесты занимали все больше и больше времени, поскольку использовалось больше памяти, поэтому простое ожидание ссылок на go не является очень хороший вариант.
И если вы не можете помочь; спасибо, что нашли время, чтобы прочитать мою стену текста ...