Как правильно полностью удалить элемент управления из родительского элемента управления / формы? - PullRequest
3 голосов
/ 09 декабря 2011

У меня есть элемент пользовательского интерфейса в моем приложении, где Panel используется для размещения одного из нескольких потенциальных пользовательских UserControls. Сама панель размещается в стандартизированном пользовательском контроле, в котором я использую что-то вроде немодального диалога, который я называю «панелью».

Метод, который я использую, - создать новый экземпляр стандартной панели, а затем с помощью логики создать один из нескольких дополнительных размещенных в нем элементов управления, используя Panel.Controls.Add(control). Затем я добавляю новую панель к элементу управления интерфейса в заданном месте, снова с помощью Control.Controls.Add(control), а затем control.BringToFront(), чтобы максимизировать его положение z.

Все это работает хорошо, однако, когда приходит время скрыть панель и уничтожить ее, я не могу полностью избавиться от нее. Первоначально я просто использовал Control.Controls.Remove(control) и для правильной меры установил для свойства Parent панели значение Nothing. Это привело бы к желаемому эффекту исчезновения панели, и я предположил, что теперь элемент управления не имеет ссылок, что GC будет им распоряжаться.

Однако я вижу, что этот элемент управления мгновенно мигает на экране, когда следующий внешний хост TabControl меняет вкладку, подразумевая, что он все еще где-то существует. Я могу подтвердить, что это не графическая проблема, и объект панели сохраняется, используя 'Make Object ID' окна VS Watch. (По крайней мере, я думаю, что это доказательство того, что без доступной для кода ссылки я все еще могу непосредственно видеть объект, и его свойства продолжают существовать.)

Я попытался заменить

Control.Controls.Remove(pane)
pane.Parent = Nothing

с

pane.Dispose()
GC.Collect()

где вызов Dispose, который я могу подтвердить, одновременно удаляет элемент управления из коллекции Controls его родителя и устанавливает для его свойства Parent значение Nothing, но, похоже, больше этого не делает. Оно сохраняется после принудительного сбора данных и время от времени вспыхивает на экране.

Все это приводит к моему первоначальному вопросу: как правильно удалить и полностью уничтожить элементы управления после того, как они выполнили свою задачу?

1 Ответ

0 голосов
/ 20 июня 2013

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

Метод Dispose должен вызывать метод GC.SuppressFinalize для объекта, который он удаляет. Если объект в данный момент находится в очереди завершения, GC.SuppressFinalize предотвращает вызов его метода Finalize.

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

Всегда вызывайте Dispose, прежде чем выпускать свою последнюю ссылку на Компонент. В противном случае используемые им ресурсы не будут освобождены до тех пор, пока сборщик мусора не вызовет метод Finalize объекта Component.

С этой статьи.

Так что либо вам нужно освободить вашу последнюю ссылку, либо вам нужно вызвать метод finalize компонентов напрямую, чтобы ваш GC.Collect () работал.

...