Будет ли сборщик мусора вызывать IDisposable. Утилизировать для меня?

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

125
задан Orion Edwards 11 May 2011 в 20:23
поделиться

9 ответов

.Net Garbage Collector называет Объект. Завершите метод объекта на сборке "мусора". значение по умолчанию это делает ничто и должно быть переопределено, если Вы хотите освободить дополнительные ресурсы.

Располагают, автоматически не назван и должен быть explicity, названный, если средства должны быть высвобождены, такой, поскольку в рамках 'использования' или 'пробуют наконец' блок

, см. http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx для получения дополнительной информации

112
ответ дан Xian 11 May 2011 в 20:23
поделиться
  • 1
    Это проверит каждую строку. Он хочет сделать единственную проверку. – JNK 19 September 2011 в 13:42

Я хочу подчеркнуть мысль Brian в его комментарии, потому что это важно.

Финализаторы не являются детерминированными деструкторами как в C++. Как другие указали, нет никакой гарантии того, когда это назовут, и действительно если у Вас будет достаточно памяти, если это будет когда-нибудь быть названным.

, Но плохая вещь о финализаторах то, что, как Brian сказал, она вызывает Ваш объект пережить сборку "мусора". Это может быть плохо. Почему?

, Как Вы можете или не можете знать, GC разделяется на поколения - Генерал 0, 1 и 2, плюс "Куча" для больших объектов. Разделение является широким термином - Вы получаете один блок памяти, но существуют указатели того, где Генерал 0 объектов запускаются и заканчиваются.

мыслительный процесс - то, что Вы будете, вероятно, использовать много объектов, которые будут недолгими. Таким образом, это должно быть легким и быстрым, чтобы GC добрался до - Генерал 0 объектов. Таким образом, когда существует давление памяти, первой вещью, которую оно делает, является Генерал 0 наборов.

Теперь, если это не разрешает достаточно давления, то оно возвращается и делает Генерала 1 развертка (восстанавливающий Генерала 0), и затем если все еще достаточно, оно делает Генерала 2 развертки (восстанавливающий Генерала 1 и Генерала 0). Так чистка долговечных объектов может требовать времени и быть довольно дорогой (так как Ваши потоки могут быть приостановлены во время операции).

Это означает это, если Вы делаете что-то вроде этого:

~MyClass() { }

Ваш объект, независимо от того, что, будет жить к Поколению 2. Это вызвано тем, что GC не имеет никакого способа назвать финализатор во время сборки "мусора". Таким образом, объекты, которые должны быть завершены, перемещены к специальной очереди, чтобы быть вычищенными другим потоком (поток финализатора - который, если Вы уничтожаете, заставляет все виды плохих вещей произойти). Это означает, что Ваши объекты бродят вокруг дольше и потенциально вызывают больше сборок "мусора".

Так, все это должно только убедительно доказать точку зрения, что Вы хотите использовать IDisposable для чистки ресурсов каждый раз, когда возможный и серьезно пытаются найти способы вокруг использования финализатора. Это находится в интересах Вашего приложения.

62
ответ дан Martin Capodici 11 May 2011 в 20:23
поделиться
  • 1
    @Imraan я думаю you' ve неправильно истолковал запрос. COUNT действия на вложенном SELECT, который имеет самое большее 1 строку (потому что эти LIMIT находится в подзапросе). – jpmc26 17 January 2014 в 11:37

Не в случае Вы описываете, Но GC будет звонить Финализатор для Вас, если у Вас будет тот.

КАК БЫ ТО НИ БЫЛО. Следующая сборка "мусора", вместо того, чтобы быть собранным, объект войдет в завершение que, все собрано, затем это - названный финализатор. Следующий набор после этого это будет освобождено.

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

3
ответ дан Brian Leahy 11 May 2011 в 20:23
поделиться

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

<час>

РЕДАКТИРОВАНИЕ: Я ушел и протестировал, только для проверки:

class Program
{
    static void Main(string[] args)
    {
        Fred f = new Fred();
        f = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("Fred's gone, and he's not coming back...");
        Console.ReadLine();
    }
}

class Fred : IDisposable
{
    ~Fred()
    {
        Console.WriteLine("Being finalized");
    }

    void IDisposable.Dispose()
    {
        Console.WriteLine("Being Disposed");
    }
}
6
ответ дан Matt Bishop 11 May 2011 в 20:23
поделиться
  • 1
    Это могло бы быть иногда быть программно легче к " выберите количество (*) из (выберите 1... предел 1), " как it' s гарантируемый всегда возвратить строку со значением количества (*) 0 или 1. – David Aldridge 9 May 2013 в 18:33

GC будет не , вызов располагает. Это может называть Ваш финализатор, но даже это не гарантируется при всех обстоятельствах.

Посмотрите этот статья для обсуждения лучшего способа обработать это.

1
ответ дан Rob Walker 11 May 2011 в 20:23
поделиться

Шаблон IDisposable был создан, прежде всего, чтобы быть названным разработчиком, если у Вас есть объект, который реализует IDispose, который разработчик должен или реализовать using ключевое слово вокруг контекста объекта или назвать Расположить метод непосредственно.

сбой, безопасный для шаблона, состоит в том, чтобы реализовать финализатор, назвав Расположение () метод. Если Вы не делаете этого, можно создать некоторые утечки памяти т.е.: Если Вы создаете некоторую обертку COM и никогда не называете Систему. Время выполнения. Interop. Маршалл. ReleaseComObject (comObject) (который был бы помещен в Расположить метод).

нет никакого волшебства в сбросе для вызова, Располагают методы автоматически кроме отслеживания объектов, которые содержат финализаторы и хранение их в таблице Finalizer GC и вызовом их, когда некоторая эвристика уборки умирает GC.

0
ответ дан Erick Sgarbi 11 May 2011 в 20:23
поделиться
  • 1
    Это лучше, потому что это будет всегда возвращать значение (TRUE или FALSE) вместо иногда Ни одного (в зависимости от Вашего языка программирования), который не мог бы развернуть способ, которым Вы ожидаете. – isaaclw 10 June 2014 в 23:18

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

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

class SomeObject : IDisposable {
 IntPtr _SomeNativeHandle;
 FileStream _SomeFileStream;

 // Something useful here

 ~ SomeObject() {
  Dispose(false);
 }

 public void Dispose() {
  Dispose(true);
 }

 protected virtual void Dispose(bool disposing) {
  if(disposing) {
   GC.SuppressFinalize(this);
   //Because the object was explicitly disposed, there will be no need to 
   //run the finalizer.  Suppressing it reduces pressure on the GC

   //The managed reference to an IDisposable is disposed only if the 
   _SomeFileStream.Dispose();
  }

  //Regardless, clean up the native handle ourselves.  Because it is simple a member
  // of the current instance, the GC can't have done anything to it, 
  // and this is the onlyplace to safely clean up

  if(IntPtr.Zero != _SomeNativeHandle) {
   NativeMethods.CloseHandle(_SomeNativeHandle);
   _SomeNativeHandle = IntPtr.Zero;
  }
 }
}

Это - простая версия, но существует много нюансов, которые могут сбить Вас с толку на этом шаблоне.

  • контракт для IDisposable. Расположите указывает, что должно быть безопасно звонить многократно (вызов Располагают на объекте, который был уже расположен, ничего не должен делать)
  • , Это может стать очень сложным для надлежащего управления иерархией наследования доступных объектов, особенно если различные слои представляют новые Доступные и неуправляемые ресурсы. В шаблоне выше Располагают (bool), является виртуальным, чтобы позволить этому быть переопределенным так, чтобы им можно было управлять, но я нахожу, что это подвержено ошибкам.

, По-моему, намного лучше полностью постараться не иметь любые типы, которые непосредственно содержат и доступные ссылки и собственные ресурсы, которые могут потребовать завершения. SafeHandles обеспечивают очень очевидный способ выполнения этого путем инкапсуляции собственных ресурсов в доступные, которые внутренне обеспечивают их собственное завершение (наряду со многими другими преимуществами как удаление окна во время P/Invoke, где собственный дескриптор мог быть потерян из-за асинхронного исключения).

Просто определение SafeHandle делает это Тривиальным:


private class SomeSafeHandle
 : SafeHandleZeroOrMinusOneIsInvalid {
 public SomeSafeHandle()
  : base(true)
  { }

 protected override bool ReleaseHandle()
 { return NativeMethods.CloseHandle(handle); }
}

Позволяет Вам упрощать содержание типа до:


class SomeObject : IDisposable {
 SomeSafeHandle _SomeSafeHandle;
 FileStream _SomeFileStream;
 // Something useful here
 public virtual void Dispose() {
  _SomeSafeHandle.Dispose();
  _SomeFileStream.Dispose();
 }
}
31
ответ дан Andrew 11 May 2011 в 20:23
поделиться
  • 1
    Количество @DavidAldridge (*) все еще означает, что все строки должны быть считаны, тогда как предел 1 остановка в первой записи и возвратах – Imraan 12 December 2013 в 13:36

Документация относительно IDisposable дает довольно ясный и подробный explaination поведения, а также пример кода. GC НЕ будет звонить Dispose() метод в интерфейсе, но он назовет финализатор для Вашего объекта.

0
ответ дан Joseph Daigle 11 May 2011 в 20:23
поделиться

Нет, это не называют.

, Но это делает легким не сделать, забывают располагать Ваши объекты. Просто используйте using ключевое слово.

я сделал следующий тест для этого:

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo();
        foo = null;
        Console.WriteLine("foo is null");
        GC.Collect();
        Console.WriteLine("GC Called");
        Console.ReadLine();
    }
}

class Foo : IDisposable
{
    public void Dispose()
    {

        Console.WriteLine("Disposed!");
    }
1
ответ дан penyaskito 11 May 2011 в 20:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: