Как сборка "мусора" работает над ссылками на объект?

Я смущен процессом сборки "мусора" на объектах.

object A = new object();
object B = A;        
B.Dispose();

Путем вызова Расположения на переменной B только, не будет собран "мусор" созданный объект, как объект, все еще сослался A.

Теперь следующее кодирует работу то же как выше?

public static image Test1()
{
    Bitmap A = new Bitmap();
    return A;
}

Теперь я вызываю эту статическую функцию из некоторого другого метода.

public void TestB()
{
   Bitmap B = Test1();
   B.Dispose();
} 

Статический функциональный Test1 возвратил ссылку на Растровый объект. Ссылка сохраняется в другой переменной B. Путем вызова Расположения на B, соединения между B и объектом потерян, но что происходит со ссылкой, которая передается от Test1. Это останется активным, пока объем функционального TestB не будет закончен?

Там какой-либо путь состоит в том, чтобы расположить ссылку, которая сразу передается от статической функции?

9
задан Azhar 13 August 2010 в 20:12
поделиться

7 ответов

Я могу отключиться, но вы, кажется, неправильно понимаете Dispose и сборку мусора. После того, как все ссылки на него исчезнут, объект будет недетерминирован сборщиком мусора. Dispose обычно избавляется от неуправляемых ресурсов, поэтому объект готов к сборке мусора. В первом примере вы удалили объект, теоретически сделав его непригодным для использования, но он все еще существует в куче, и у вас все еще есть ссылка на него, как A, так и B. Как только они выходят за пределы области видимости, сборщик мусора может вернуть эту память , но не всегда. В примере 2 Bitmap A помещается в кучу, затем вы возвращаете ссылку на него и устанавливаете B на эту ссылку. Затем вы утилизируете его, и B выходит за рамки. На этом этапе больше не существует ссылок на него, и он будет удален позже.

15
ответ дан 4 December 2019 в 06:11
поделиться

Dispose выполняет не сборщик мусора. Вы не можете явно собрать мусор для конкретного объекта. Вы можете вызвать GC.Collect () , который запрашивает запуск сборщика мусора, но это не то же самое. Вызов Dispose даже не «отключает» объект от конкретной переменной, на самом деле ...пока эта переменная остается активной (до последнего момента, когда JIT может определить, что она когда-либо будет прочитана снова), она предотвратит сборку мусора для объекта.

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

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

17
ответ дан 4 December 2019 в 06:11
поделиться

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

Фундаментальный вопрос в сборке мусора: «Можно ли достичь этого объекта?» Пока в стеке есть объект, который имеет ссылку на ваш объект (или есть ссылка на этот объект где-то в иерархии объектов), этот объект не будет собираться сборщиком мусора.

Пример:

ObjA создает ObjB, который создает ObjC. Obj C не будет собираться сборщиком мусора до тех пор, пока на него больше не будет ссылаться ObjB, или пока ObjB не перестанет ссылаться на ObjA, или пока не будет объектов, которые сохраняют ссылку на ObjA.

И снова возникает вопрос: «Может ли на данный момент на этот объект ссылаться что-либо в коде?»

0
ответ дан 4 December 2019 в 06:11
поделиться

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

3
ответ дан 4 December 2019 в 06:11
поделиться

Здесь много хороших ответов, но я также хотел бы указать, что причина, по которой люди думали, что вам нужен IDisposable, заключается в том, что сборщик мусора действительно должен называться MemoryCollector или даже ManagedMemoryCollector.Сборщик мусора не особенно умен, когда дело доходит до сбора неуправляемых ресурсов памяти, таких как файлы, соединения с базами данных, транзакции, дескрипторы окон и т. Д.

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

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

С дескрипторами Windows нам нужно беспокоиться о привязке к потокам. Поскольку сборщик мусора работает в выделенном потоке, этот поток всегда является неправильным потоком для освобождения дескрипторов окон.

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

Использование оператора () - это благословение.

PS. Довольно часто я реализую IDisposable, хотя у меня нет прямых неуправляемых ресурсов, но его импорт не предназначен для информирования всех переменных-членов, реализующих IDisposable, которые были вызваны Dispose.

2
ответ дан 4 December 2019 в 06:11
поделиться

Так получилось, что Раймонд Чен только что написал серию сообщений в блоге, описывающих аспекты сборки мусора .NET. Этот пост напрямую связан с вашим вопросом (когда объекты собираются сборщиком мусора?).

5
ответ дан 4 December 2019 в 06:11
поделиться

Хорошо для начала Dispose! = Мусор собран. Вы можете вызвать dispose и никогда не собирать мусор, потому что «Disposed Object» все еще может иметь ссылки на него. Метод dispose используется для «уборки» объекта перед запуском CG (закрытие открытых соединений с базами данных или файловых соединений и т. Д.).

object A = new object();
object B = A;        
B.Dispose();

В этом случае B.Dispose вызывает метод dispose для A, потому что B ссылается на объект в переменной A. Также не будет CGd, потому что они еще не вышли из области видимости.

public static image Test1()
{
    Bitmap A = new Bitmap();
    return A;
}

Здесь происходит то, что вы создаете объект A и возвращаете его, поэтому, когда вы покидаете Test1, A, скорее всего, ссылается на другую переменную в вызывающем методе. Это означает, что даже если вы покинули метод, A все еще имеет root-права (скорее всего) и не будет CG'd, пока вызывающий метод не завершит работу с ним.

public void TestB()
{
   Bitmap B = Test1();
   B.Dispose();
} 

Здесь B создается и вызывает команду dispose. Это не значит, что он будет собираться мусором. Как только программа покидает метод, B выпадает из области видимости, что означает, что он может быть собран при следующем вызове GC.

Когда использовать Dispose

1
ответ дан 4 December 2019 в 06:11
поделиться
Другие вопросы по тегам:

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