Что происходит с памятью, когда вкладка удаляется из коллекции элементов?

Я собираюсь использовать псевдокод в этом вопросе, поэтому, пожалуйста, обратитесь к этому в теоретическом аспекте (я имею в виду, что будут некоторые упрощения)

Предположим такую ​​ситуацию:

У меня есть Главное окно моего приложения, у которого есть TabControl. Чтобы удалить элемент из своей коллекции, я использую функцию статическийГлавное окно следующим образом:

public static void CloseTab(string someKindOfTabIdentity)
{
    var tab = myTabControl.Items.FirstOfDefault(someScenario);
    if (tab != null)
    {
        myTabControl.Items.Remove(tab);
        tab.Content = null;
        tab = null;
        GC.Collect();
    }
}

Теперь у меня есть Страница 1, где я разрешаю пользователю закрывать вкладку через какую-то функцию, скажем

private void GoToPage2()
{
    MainWindow.CreatePage2AddToTabControlAndNavigateToIt()
    MainWindow.CloseTab(myCurrentPage1Tab);
    App.Cursor = Cursors.Arrow;
}

Эта функция должна создать новую вкладку, назначить ей содержимое, а затем с помощью MainWindow.CloseTab(myCurrentPage1Tab); закрыть текущую вкладку, содержащую Страница 1.

Вот вопросы:

  1. Что происходит с выделением памяти Страница 1 после строки MainWindow.CloseTab(myCurrentPage1Tab);?

  2. Что происходит с выделением памяти Страница 1, если после строки MainWindow.CloseTab(myCurrentPage1Tab); есть код?

  3. Когда Страница 1 будет полностью освобожден из памяти?

  4. Есть ли лучший (более эффективный) способ добиться этого?

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

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

Laurent Lequenne 10.04.2019 15:28

Обратите внимание, что установка tab = null перед вызовом myTabControl.Items.Remove(tab) не имеет особого смысла даже в псевдокоде.

Clemens 10.04.2019 15:35

@ Клеменс, конечно, нет, я отредактирую, спасибо.

Vanghern 10.04.2019 15:38

@LaurentLequenne, не могли бы вы расширить свой ответ?

Vanghern 10.04.2019 15:41

Я бы порекомендовал правильно разместить вкладку, а не просто установить для нее значение null. Установка его на null будет работать, однако потребуется некоторое время, прежде чем сборщик мусора сработает и полностью удалит его.

Tejus 10.04.2019 15:41

GC.Collect() не обязательно должен немедленно собирать объект для утилизации. Есть некоторые исключения. Пожалуйста, прочтите раздел «Примечания» по этой ссылке. docs.microsoft.com/en-us/dotnet/api/…

Tejus 10.04.2019 15:46

GC.Collect() не удаляет объекты. Все элементы управления winforms используют неуправляемые ресурсы и должны быть удалены. Если вы создаете динамические вкладки или любой другой элемент управления winform, вы добавляете обработчики ресурсов Windows, которые ограничены. в сумме.

Laurent Lequenne 11.04.2019 21:48
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
55
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

1-3

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

Когда какой-то элемент управления очищается сборщиком, обычно это не имеет значения. Если это относится к вам, возможно, у вас есть проблема в вашем дизайне.

4

Зависит от того, что вы делаете. Почти все команды разработчиков используют mvvm с wpf. Обычный подход заключается в том, чтобы привязать набор моделей представления к источнику элементов этого элемента управления вкладками и шаблонировать их на вкладках. Удаление вкладки повлечет за собой удаление модели представления из этого списка.

При таком подходе только текущая вкладка будет шаблонизирована в пользовательском интерфейсе.

Однако ваше описание похоже на навигацию. Распространенным шаблоном, используемым для навигации в стиле mvvm, является представление модели в первую очередь (вы должны найти кучу примеров в Google). По сути, это будет включать в себя предоставление свойства из модели представления окна, которое будет содержать модель представления для текущего представления. Это будет связано с содержимым элемента управления контентом и шаблоном в пользовательском интерфейсе на основе типа данных.

Ответ принят как подходящий
  1. Экземпляр Page1 станет доступным для сборки мусора при условии, что на него не ссылается какой-либо другой объект, который все еще жив.
  2. Ничего дополнительного, если только «код после строки MainWindow.CloseTab(myCurrentPage1Tab);» не делает что-то со ссылкой Page1, что препятствует сбору экземпляра.
  3. Когда сборщик мусора соберет его. Когда это происходит, это недетерминировано, т.е. вы действительно не знаете, когда это произойдет, и вас это не должно волновать.
  4. Ну, нет причин явно вызывать GC.Collect. Это почти всегда плохая идея. Если экземпляр Page1 больше не упоминается в вашем приложении, он все равно будет собираться в конце концов. Кроме того, я не знаю, почему вы используете статические методы, но я думаю, что это другая история.

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

К сожалению, у меня есть несколько звонков GC.Collect(), и пока я не могу их удалить. Я начал несколько дискуссий здесь, на SO и на форумах MSDN, об утечках памяти и памяти. Поскольку мое приложение страдает от плохого распределения памяти, мне иногда нужно вызывать GC...

Vanghern 11.04.2019 09:46

Другие вопросы по теме