C # памяти и распоряжаться связанными вопросами - PullRequest
0 голосов
/ 24 декабря 2009

У меня есть следующий фрагмент кода, просто хотел проверить, кто вызовет утилизацию? это вызывается автоматически.

ToolTip toolTip = new ToolTip();
toolTip.SetToolTip(button, toolTipText);

Также позвольте мне сказать, что я создаю локальную переменную Timer, которая будет вызывать dispose, как насчет утечек памяти, так как, если я вызову dispose сразу, событие timer не будет запущено.

Нужно ли мне убедиться, что в обработчике событий таймера вызывается dispose, даже если у меня нет ссылок на переменную таймера. Также мне нужно отменить регистрацию обработчика событий для этого таймера.

Edit:

  • Но как вызвать dispose на всплывающей подсказке, если я позвоню, он не покажет.
  • Кроме того, зачем мне распоряжаться таймером, если у меня нет ссылок.
  • И нужно ли также отменить регистрацию обработчика событий таймера?
  • Сохранение ссылки также увеличивает объем памяти класса.

Ответы [ 5 ]

6 голосов
/ 24 декабря 2009

ToolTip регистрирует обработчики событий в элементе управления, на котором оно отображается. Это метод Hide () автоматически вызывается при возникновении события Deactivate формы. Что произойдет, когда форма закрыта. Это, в свою очередь, гарантирует, что его дескриптор Windows будет уничтожен, а обработчики событий не зарегистрированы. После этого не осталось одноразовых предметов.

Вы можете убедиться в этом сами с помощью Reflector или Reference Source. Соответствующими методами по порядку являются BaseFormDeactivate, HideAllToolTips, Hide, ClearTopLevelControlEvents.

Вам не нужно вызывать Dispose (), у вас нет утечки.

2 голосов
/ 24 декабря 2009

Утилизация - это метод, позволяющий немедленно освободить объект. Например, эксклюзивный файловый поток.

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

Вам нужно беспокоиться об утилизации только тогда, когда объект использует эксклюзивные или ограниченные ресурсы. Примерами являются файл или подключение к базе данных. (Обратите внимание, что в обоих этих случаях Close эквивалентен утилизации)

Чтобы ответить на ваш вопрос, вы вообще не утилизируете, а запускаете финализатор, когда это необходимо.

1 голос
/ 24 декабря 2009

В .NET сборщик мусора автоматически освобождает память, когда на объект больше нельзя ссылаться откуда-либо. Когда это происходит, если у объекта есть финализатор, он вызывает финализатор. Финализатор предназначен для очистки, как правило, неуправляемых ресурсов.

Однако финализаторы стоят дорого (например, они задерживают сборку мусора на объекте), и вы не можете сказать, когда он будет запущен (как вы не можете сказать, когда GC решит его собрать). Их обычно оставляют в качестве последнего средства для очистки таких вещей, как неуправляемые ресурсы.

Именно здесь вступает интерфейс IDisposable и его метод Dispose. Dispose также может использоваться для очистки как управляемых, так и неуправляемых ресурсов. Когда вы вызываете метод Dispose, он очищается, и объект больше не находится в стабильном и пригодном для использования состоянии.

Если у вас есть ресурс, который реализует IDisposable, вы можете вызвать Dispose, когда вы знаете, что все готово. Таким образом и ресурсы, за которые он держится, могут быть освобождены как можно скорее. Обычный способ сделать это состоит в том, чтобы заключить его в оператор using, который автоматически удалится после завершения использования блока. e.g.:

using (SomeDisposableObject disposableObject = new SomeDisposableObject())
{
     disposableObject.DoSomeStuff();
     disposableObject.DoSomeMoreStuff();
}

Когда использование блока завершено (после DoMoreStuff) Dispose вызывается для одноразового объекта. Использование операторов намного чище, чем эквивалентный код, если принять во внимание обработку исключений.

В случае чего-то вроде всплывающей подсказки, которая имеет неуправляемые ссылки (множество WinForms в оболочке вокруг неуправляемых компонентов Win32), она будет иметь финализатор, обеспечивающий вдвойне уверенность в том, что неуправляемые ресурсы освобождаются правильно. Однако, если вы вызываете Dispose для объекта, тут же запускается код очистки, и финализатор подавляется (он не запускается, когда объект собирается GC).

Итак, чтобы ответить на ваш вопрос более прямо, если вы точно знаете, когда заканчивается IDisposable, неплохо было бы позвонить в Dispose. Однако, если вы этого не сделаете, то обычно нормально оставить его на сборщик мусора, чтобы собрать его и вызвать соответствующий код для правильной очистки объекта.

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

1 голос
/ 24 декабря 2009

Вам нужно вызвать Dispose для всего, что реализует IDisposable, или, по крайней мере, убедиться, что что-то делает. Для компонентов пользовательского интерфейса добавьте их в коллекцию Controls формы, и они будут удалены после закрытия формы. Для других вещей вам нужно сохранить ссылку на них и вызвать dispose соответствующим образом. Может быть целесообразно сделать так, чтобы ваш класс реализовывал IDisposable, просто вызывая Dispose для ваших составных объектов.

0 голосов
/ 24 декабря 2009

Как правило, от объекта требуется зарегистрироваться, чтобы отменить регистрацию - не выполнение этого приведет к утечкам памяти. Вы не должны полагаться на метод Dispose при этом.

Dispose не вызывается автоматически, если вы не заключили объект в оператор using () {} или не добавили его в экземпляр IContainer объектов (если это класс конструктора). Если это переменная класса, вам нужно заставить содержащий класс реализовать IDisposable и избавиться от экземпляра в нем.

...