2015-02-12 3 views
8

Так что у меня это просто Белл класс, который я тестирую сбор мусора на:Сбор мусора - один работает, но не другой, как получилось?

public class Bell 
{ 
    public void Ring() 
    { 
     Console.WriteLine("Ding ding"); 
    } 
} 

Если я запускаю этот сегмент кода ниже, он не получает мусор, собранные

class Program 
{ 
    private static WeakReference reference; 

    private static void Main() 
    { 
     Console.WriteLine("Starting"); 

     var bell = new Bell(); 
     reference = new WeakReference(bell); 
     bell = null; 

     GC.Collect(); 

     Console.WriteLine("Object still alive: {0}", reference.IsAlive); 

     if (reference.Target == null) 
     { 
      Console.WriteLine("Bell is no more!"); 
     } 
     else 
     { 
      { 
       var theBell = (Bell)reference.Target; 
       theBell.Ring(); 
      } 
     } 

     Console.ReadLine(); 
    } 
} 

Если я однако только проверить reference.IsAlive, как показано ниже, это мусора

class Program 
{ 
    private static WeakReference reference; 

    private static void Main() 
    { 
     Console.WriteLine("Starting"); 

     var bell = new Bell(); 
     reference = new WeakReference(bell); 
     bell = null; 

     GC.Collect(); 

     Console.WriteLine("Object still alive: {0}", reference.IsAlive); 

     Console.ReadLine(); 
    } 
} 

Может вы, ребята, объясните мне, как это работает?

+1

Это работает для меня в LINQPad, но когда я пробовал его в VS 2013, он всегда собирался - debug/release, .NET 3.5, 4.0, 4.5, 4.5.1 – Ondra

ответ

2

Это из-за ваш тип объекта из reference (source)

Представляет слабую ссылку, которая ссылается на объект, в то же время позволяя , что объект будет утилизирован в процессе сборки мусора.

И следуя, вероятно, может объяснить, почему два сценария ведут себя по-разному (Source)

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

После нескольких циклов [С некоторыми тестами]: мое мнение

if-else ключом я думаю. После Writeline объект повторно ссылается, чтобы получить сильную ссылку до того, как GC очистит объект.

Опять эта фраза является ключом

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

+2

Но это то же самое в обоих случаях, он спрашивая о ... –

+0

@ Justin Harvey - правда. .I скорее сохранил бы это как объяснение, а не правильный ответ. –

+1

Перечитав теперь, что вы немного расширились, я склонен согласиться, хотя это не совсем полный ответ на вопрос, это полезная информация и помогает объяснить полный ответ. –

6

Вы пытаетесь протестировать его в режиме отладки. GC не агрессивен в режиме отладки, поскольку он ведет себя в режиме деблокирования (при включенном оптимизированном переключателе). Это упрощает отладку, иначе вы сможете найти странные вещи при отладке. Например: вы можете попытаться проверить значение уже собранной мусорной переменной.

Запустите код в режиме деблокирования, и вы увидите, что Bell будет GC'd.

+0

Я могу проверить это, только что попробовав. –

+0

Это имеет смысл, однако, см. Мой комментарий к вопросу. Он всегда собирается в моем случае, поэтому должно быть больше правил. – Ondra