C # распределение памяти и шаблоны освобождения - PullRequest
8 голосов
/ 27 апреля 2010

Поскольку C # использует сборщик мусора. Когда необходимо использовать .Dispose, чтобы освободить память?

Я понимаю, что есть несколько ситуаций, поэтому я попытаюсь перечислить те, о которых я могу подумать.

  1. Если я закрою форму, содержащую объект типа GUI, будут ли эти объекты разыменованы и, следовательно, будут собраны?
  2. Если я создаю локальный объект, используя new, я должен. Утилизировать его до выхода из метода или просто позволить GC позаботиться об этом? Что такое хорошая практика в этом случае?
  3. Бывают ли случаи, когда принуждение к ГК понятно?
  4. Собираются ли события GC, когда собирается его объект?

Ответы [ 5 ]

10 голосов
/ 27 апреля 2010

Теоретически, если вы правильно определили компоненты, никогда не нужно требовать вызова Dispose () для ваших объектов, так как финализатор должен в конечном итоге позаботиться об этом.

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

Для некоторых ваших конкретных очков:

1) Если вы знаете, что «сделали» с формой, вы можете вызвать Dispose () для нее. Это приведет к очистке в этот момент времени неуправляемых ресурсов , связанных с формой *1011*.

2) В этом случае: если ваш объект просто используется в этом методе, используйте вместо него «using»:

using (MyObject myObject = new MyObject())
{
   // use your object
} // It'll be disposed of here for you

3) Есть редкие причины сделать это, но в целом нет.

4) События - это делегаты - память, связанная с делегатом, будет собрана после того, как сам делегат станет рутированным, что обычно происходит, когда рассматриваемые объекты не рутированы.

3 голосов
/ 27 апреля 2010

Вы должны вызывать Dispose для каждого класса, который реализует IDisposable . Если бы он не нуждался в Dispose ed, он бы не реализовал IDisposable.

Что касается других ваших вопросов:

  1. Когда вы добавляете элемент управления в коллекцию формы Controls, он автоматически удаляется при закрытии формы, поэтому вам там ничего не нужно делать.
  2. Если объект реализует IDisposable, то вам нужно вызвать Dispose. Например, если вы идете new FileStream(...), то FileStream необходимо удалить, поскольку он реализует IDisposable. Я бы посоветовал вам прочитать конструкцию using в C #, которая упрощает обработку IDisposable объектов.
  3. Не совсем, в 99,99% случаев сборщик мусора будет знать, когда лучше всего запускаться. Это одна из тех ситуаций, «вы будете знать, когда вам это нужно».
  4. Если на объект, содержащий событие, больше не ссылаются, то логически любые ссылки на объекты, содержащиеся в событии, также больше не ссылаются и будут доступны для сбора.
2 голосов
/ 27 апреля 2010

Посмотрите на этот вопрос:

Существует ли распространенная практика облегчения освобождения памяти для сборщика мусора в .NET?

Если ваш класс создает экземпляр интерфейса IDisposable, это (вероятно) означает, что у него есть системные ресурсы, которые необходимо утилизировать напрямую. Один из простых способов сделать это - использовать ключевое слово using, например:

using(var g = Graphics.FromBitmap(bmp))
{
    //Do some stuff with the graphics object
}

за ответ @Matt S на этот вопрос, на который я ссылался.

На ваши вопросы:

  1. Если вы создаете экземпляр объекта, который имеет IDisposable, вам нужно будет утилизировать его при закрытии формы. Это сложно в WPF и просто в Winforms, так как в диалоговых окнах winforms есть методы Dispose. Что касается WPF, я решил эту проблему, сохранив класс WPF, но скрытый, вызвав метод dispose, который удаляет все объекты (например, последовательные порты), а затем устанавливает для класса WPF значение null.
  2. Нет. Пусть GC позаботится об этом.
  3. Думаю, что так, но я получил негативные голоса :) Когда я сделал очень большие ассигнования, заставить GC удалить их, это, я думаю, хорошая идея.
  4. Я не уверен. Я думаю, что события сами по себе являются объектами, поэтому будут собираться, когда они больше не будут использоваться.
1 голос
/ 27 апреля 2010

Как сказал Рид Копси, обычно нет необходимости звонить в Dispose.

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

Form_Load(...)
    MyState.Instance.AddressChanged += this.User_AddressChanged;
End

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

0 голосов
/ 27 апреля 2010

Если вы используете объект IDisposable, попробуйте использовать оператор using, чтобы автоматически обработать для вас утилизацию.

...