2015-02-12 18 views
8

Così ho questo semplicemente classe di Bell che sto testando garbage collection on:Garbage collection - Uno funziona ma non l'altro, come mai?

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

Se corro questo segmento di codice di seguito, non ottiene garbage collection

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(); 
    } 
} 

Se invece controlla solo il riferimento.Ilivello come di seguito, è la raccolta dei rifiuti

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(); 
    } 
} 

Potete dirmi come funziona?

+1

Funziona lo stesso per me in LINQPad, ma quando l'ho provato in VS 2013 è stato sempre raccolto - debug/release, .NET 3.5, 4.0, 4.5, 4.5.1 – Ondra

risposta

2

Questo è a causa del vostro tipo di oggetto di reference (source)

rappresenta un riferimento debole, che fa riferimento a un oggetto, pur consentendo quell'oggetto da bonificare dal garbage collection.

E seguenti potrebbe probabilmente spiegare perché due scenari comportano in modo diverso (Source)

Un riferimento debole permette al garbage collector di raccogliere l'oggetto, pur consentendo l'applicazione per accedere all'oggetto. Un riferimento debole è valido solo durante l'intervallo di tempo indeterminato finché l'oggetto non viene raccolto quando non esistono riferimenti forti. Quando si utilizza un riferimento debole, l'applicazione può ancora ottenere un riferimento forte all'oggetto, che ne impedisce la raccolta. Tuttavia, c'è sempre il rischio che il garbage collector raggiunga l'oggetto prima che venga ristabilito un riferimento forte.

Dopo diverse piste [Con alcuni casi di test]: mio parere

Il if-else è la chiave credo. Dopo Writeline, l'oggetto viene rinominato consentendo di ottenere un riferimento forte prima di GC pulire l'oggetto.

Anche questa frase è la chiave

Tuttavia, v'è sempre il rischio che il garbage collector otterrà all'oggetto prima viene ristabilito un riferimento forte.

+2

Ma questo è lo stesso in entrambi i casi chiedendo informazioni su ... –

+0

@Justin Harvey - true. .i preferisco mantenere questo come una spiegazione piuttosto che la risposta corretta .. –

+1

Rileggendo ora che hai allargato un po ', sono propenso a concordare, mentre non è proprio la risposta completa alla domanda, è un'informazione utile e aiuta a spiegare la risposta completa. –

6

Stai provando a testarlo con la modalità di debug. GC non è aggressivo in modalità debug in quanto si comporta in modalità di rilascio (con l'interruttore di ottimizzazione attivato). Questo facilita il debug, altrimenti troverai strane cose durante il debug. Ad esempio: puoi provare a controllare il valore della variabile già raccolta.

Eseguire il codice in modalità di rilascio e è possibile vedere Bell sarà GC'd.

+0

Posso verificare che abbia appena provato. –

+0

Questo ha senso, tuttavia vedi il mio commento alla domanda. Viene sempre raccolto nel mio caso, quindi ci devono essere più regole. – Ondra