C# WPF Утечка памяти, когда Window имеет TabControl с TabItem (или отложенное восстановление памяти?) - PullRequest
0 голосов
/ 15 января 2020

Я столкнулся с очевидной утечкой памяти в приложении, которое открывало окно настроек, содержащее 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 не является очень хороший вариант.

И если вы не можете помочь; спасибо, что нашли время, чтобы прочитать мою стену текста ...

1 Ответ

0 голосов
/ 15 января 2020

Установить владельца TabWindow's

private void Button_Click(object sender, RoutedEventArgs e)
{
       TabsWindow w = new TabsWindow();
       w.Owner = this;
       w.Show();
}
...