Если объект был удален, спасает ли его подавление финализатора gc? - PullRequest
4 голосов
/ 20 марта 2012

Сборка мусора может стать трудоемким процессом.В связи с этим GC стремится работать только тогда, когда это необходимо.Если объект был удален, чтобы сэкономить время и помочь ГХ, следует ли подавить финализатор ГХ?

using(var sO = new someObject())
{
 //work with object
}

public class someObject : IDisposable
{
  internal Stream someResource;
  internal Context someContext;

  public void Dispose()
  {
   someContext.Dispose();
   someResource.Dispose();
   //A: does suppressing the GC finalizer here save time for the GC?
   //B: can this cause memory leaks?
   //GC.SuppressFinalize(this);
  }
}

Ответы [ 3 ]

4 голосов
/ 20 марта 2012

Чтобы устранить некоторую путаницу:

  • Финализатор нужен только в том случае, если вам нужно каким-то особым образом очистить неуправляемые ресурсы.

  • Если у вас нет неуправляемых ресурсов, вам не нужен финализатор.

  • Если у вас есть финализатор, то вам обязательно нужно реализовать IDisposable.

  • Если у вас есть финализатор, вам следует вызвать GC.SuppressFinalize в Dispose, потому что финализатор не нужно вызывать, если вы уже очистились после себя.

  • Вам нужно только вызвать GC.SuppressFinalize, если у вас есть финализатор. Если вы этого не сделаете, вы, вероятно, все равно хотите назвать это в качестве защитной меры.

ли подавление финализатора GC здесь экономит время для GC?

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

Если у вас нет финализатора, вы говорите, что у вас нет ничего неуправляемого для очистки. Вы все равно должны вызывать SuppressFinalize в качестве защитной меры.

Из правил FxCop:

«Неспособность подавить финализацию снижает производительность и не дает никаких преимуществ.»


На ваш другой вопрос,

может ли это вызвать утечку памяти?

В этом примере да, если какой-либо из ресурсов неуправляем. Если ваш объект завершается каким-либо необычным образом, прежде чем он может вызвать Dispose, неуправляемые ресурсы не будут должным образом освобождены. Подумайте, что произойдет, если someResource неуправляем и выдает исключение, например, при использовании экземпляра someObject.

Если ваш объект удерживает неуправляемые ресурсы, и вам нужно гарантировать, что эти ресурсы очищены, вам также нужен финализатор (который в вашем случае будет называться ~someObject).

3 голосов
/ 20 марта 2012

Если вы активно Dispose объект, то да, вы должны подавить завершение.Нет необходимости завершать объект, если вы активно / детерминистически высвобождаете все ресурсы.Позволить ему зависнуть для финализатора - это просто напрасная трата времени.

1 голос
/ 30 октября 2012

Один момент, о котором еще не говорилось: объект нужно считать «живым», только если существует некоторый путь выполнения, через который коду может понадобиться доступ к его полям или заголовку объекта (структура данных, которая содержит информацию о типе объекта, будь тоон использовался в качестве блокировки монитора и т. д.) Если поле объекта содержит неуправляемый дескриптор, а последнее, что делает метод Dispose, - это закрывает дескриптор, возможно, объект может получить право на финализацию , покаDispose метод запущен .К сожалению.Мало того, что вызов GC.SuppressFinalize будет служить для предотвращения постановки в очередь финализатора после его выполнения;его размещение в качестве последнего действия Dispose не позволит объекту получить право на завершение до того, как выполнится.

...