Обновление: Я попробовал это на другом, более чисто установленном, машина. Я не мог воспроизвести это на той машине. Если я узнаю то, что, нарушая (VSStudio) компонент вызывает это, то я сообщу.
Я создаю некоторый UIElements из кода позади, и ожидал сборку "мусора" для разрешения материала. Однако объекты не являются свободным редактором в то время, когда я ожидал это. Я ожидал, что они будут освобождены в RemoveAt (0), но они только освобождены в конце программы.
Как я могу заставить объекты быть освобожденными при удалении из Дочернего набора Холста?
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
MouseDown="Window_MouseDown">
<Grid>
<Canvas x:Name="main" />
</Grid>
</Window>
Код позади:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
GC.Collect(); // This should pick up the control removed at a previous MouseDown
GC.WaitForPendingFinalizers(); // Doesn't help either
if (main.Children.Count == 0)
main.Children.Add(new MyControl() { Background = Brushes.Yellow, Width = 100, Height = 50 });
else
main.Children.RemoveAt(0);
}
}
public class MyControl : UserControl
{
~MyControl()
{
Debug.WriteLine("Goodbye");
}
}
Измените
открытый класс MyControl: UserControl
на
открытый класс MyControl: ContentControl
, и он попрощается (после второго удаления элемента управления.) Я также проверил отсутствие утечек памяти, используя
Debug.WriteLine ("mem:" + GC.GetTotalMemory (true) .ToString ());
Также см. this :
Вы удаляете TestControl, очищая grid.Children, но он не сразу подходит для сборки мусора. Несколько асинхронных операций с ним ожидают выполнения, и сборщик мусора не может быть завершен до тех пор, пока эти операции не будут завершены (к ним относятся создание события Unloaded и некоторого кода очистки в механизме рендеринга).
Я проверил, что если вы дождетесь завершения этих операций (скажем, запланировав операцию Dispatcher с приоритетом ContextIdle), TestControl станет подходящим для GC, независимо от наличия привязки к TextBlock.
UserControl должен либо иметь внутреннее событие, которое не очищается быстро, либо это может быть ошибка VS2010 RC. Я бы сообщил об этом через connect, а пока переключился на ContentControl.
Поскольку вы используете UserControl, я предполагаю, что вам также придется переключиться на использование шаблона Generic.xaml. Это не так уж сложно (и для большинства вещей это лучшее решение).
Объекты в C # не освобождаются автоматически, как только они больше не используются.
Скорее, когда вы удаляете объект из своего Control, он становится подходящим для сборки мусора в этот момент, если у вас нет других ссылок на этот UIelement.
После того, как объект «не рутирован» (нет прямых или косвенных ссылок на какой-либо используемый объект в вашем приложении), он становится пригодным для сбора. Затем сборщик мусора в конечном итоге очистит ваш объект, но когда это происходит, вы (обычно) не контролируете.
Просто верьте, что со временем он будет очищен. В этом прелесть C # (и .NET в целом) - управление этим и забота о нем ложатся на вас.
Правка: после некоторого тестирования выяснилось, что окно содержит ссылку на UIelement до следующего прохода макета. Вы можете заставить это произойти, добавив вызов к:
this.UpdateLayout();
После удаления элемента (ов) с холста Children. Это сделает объекты доступными для сборки мусора.
У нас была та же проблема, и мы тоже думали, что это может быть причиной. Но мы проанализировали наш проект с помощью инструментов профилирования памяти и обнаружили, что тут нет ничего общего с Grid.Remove или Grid.RemoveAt. Поэтому я думаю, что я предлагаю просто взглянуть на ваш проект в инструменте профилирования памяти и посмотреть, что происходит внутри вашего проекта. надеется, что это поможет.
В C # существует 3 поколения сборки мусора, поэтому даже если на ваши объекты нет ссылок, для их освобождения может потребоваться 3 сборки мусора.
Вы можете использовать параметр GC.Collect () для принудительной сборки мусора 3-го поколения,
однако лучший способ - не вызывать GC.Collect () самостоятельно,
вместо этого используйте интерфейс IDisposable и привяжите дочерние элементы к ObservableCollection
, а когда вы получите событие Dispose () CollectionChanged для любых удаленных объектов.