Я собираюсь использовать псевдокод в этом вопросе, поэтому, пожалуйста, обратитесь к этому в теоретическом аспекте (я имею в виду, что будут некоторые упрощения)
Предположим такую ситуацию:
У меня есть Главное окно моего приложения, у которого есть 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 после строки MainWindow.CloseTab(myCurrentPage1Tab);
?
Что происходит с выделением памяти Страница 1, если после строки MainWindow.CloseTab(myCurrentPage1Tab);
есть код?
Когда Страница 1 будет полностью освобожден из памяти?
Есть ли лучший (более эффективный) способ добиться этого?
Этот упрощенный сценарий — это то, что постоянно происходит с моим приложением WPF, и меня беспокоит, является ли это безопасным способом управления элементами вкладок и памятью моего приложения.
Обратите внимание, что установка tab = null
перед вызовом myTabControl.Items.Remove(tab)
не имеет особого смысла даже в псевдокоде.
@ Клеменс, конечно, нет, я отредактирую, спасибо.
@LaurentLequenne, не могли бы вы расширить свой ответ?
Я бы порекомендовал правильно разместить вкладку, а не просто установить для нее значение null. Установка его на null будет работать, однако потребуется некоторое время, прежде чем сборщик мусора сработает и полностью удалит его.
GC.Collect() не обязательно должен немедленно собирать объект для утилизации. Есть некоторые исключения. Пожалуйста, прочтите раздел «Примечания» по этой ссылке. docs.microsoft.com/en-us/dotnet/api/…
GC.Collect() не удаляет объекты. Все элементы управления winforms используют неуправляемые ресурсы и должны быть удалены. Если вы создаете динамические вкладки или любой другой элемент управления winform, вы добавляете обработчики ресурсов Windows, которые ограничены. в сумме.
1-3
Сборщик мусора удалит элементы управления, на которые не ссылаются, из памяти, когда дойдет до этого. Когда именно это произойдет, будет зависеть от того, что еще делает ваше приложение.
Когда какой-то элемент управления очищается сборщиком, обычно это не имеет значения. Если это относится к вам, возможно, у вас есть проблема в вашем дизайне.
4
Зависит от того, что вы делаете. Почти все команды разработчиков используют mvvm с wpf. Обычный подход заключается в том, чтобы привязать набор моделей представления к источнику элементов этого элемента управления вкладками и шаблонировать их на вкладках. Удаление вкладки повлечет за собой удаление модели представления из этого списка.
При таком подходе только текущая вкладка будет шаблонизирована в пользовательском интерфейсе.
Однако ваше описание похоже на навигацию. Распространенным шаблоном, используемым для навигации в стиле mvvm, является представление модели в первую очередь (вы должны найти кучу примеров в Google). По сути, это будет включать в себя предоставление свойства из модели представления окна, которое будет содержать модель представления для текущего представления. Это будет связано с содержимым элемента управления контентом и шаблоном в пользовательском интерфейсе на основе типа данных.
Page1
станет доступным для сборки мусора при условии, что на него не ссылается какой-либо другой объект, который все еще жив.MainWindow.CloseTab(myCurrentPage1Tab);
» не делает что-то со ссылкой Page1
, что препятствует сбору экземпляра.GC.Collect
. Это почти всегда плохая идея. Если экземпляр Page1
больше не упоминается в вашем приложении, он все равно будет собираться в конце концов. Кроме того, я не знаю, почему вы используете статические методы, но я думаю, что это другая история.Подводя итог, вы должны просто убедиться, что в вашем коде нет ссылок, которые поддерживают жизнь страницы дольше, чем необходимо, но не мешать сборщику мусора.
К сожалению, у меня есть несколько звонков GC.Collect()
, и пока я не могу их удалить. Я начал несколько дискуссий здесь, на SO и на форумах MSDN, об утечках памяти и памяти. Поскольку мое приложение страдает от плохого распределения памяти, мне иногда нужно вызывать GC...
Удаление вкладки из элемента управления вкладками не означает, что ваша вкладка не имеет ссылки, если она одноразовая, вы также должны удалить вкладку.