2011-08-31 8 views
5

Nel seguente codice, creo un DispatcherTimer nel costruttore della classe. Nessuno continua a farvi riferimento.Garbage collection dell'oggetto C# dichiarato nel costruttore

A mio parere, il timer deve essere recuperato dal garbage collector qualche tempo dopo aver abbandonato l'ambito del costruttore. Ma questo non succede! Anche dopo aver forzato una garbage collection con GC.Collect()

Cosa sta succedendo sotto il cofano?

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     new DispatcherTimer 
     { 
      Interval = TimeSpan.FromMilliseconds(100), 
      IsEnabled = true 
     } 
     .Tick += (s, e) => 
     { 
      textBlock1.Text = DateTime.Now.ToString(); 
     }; 
    } 
} 

risposta

3

Quando si costruisce il a DispatcherTimer, nulla gli impedisce di essere sottoposto a GC. Tuttavia, si imposta IsEnabled = true, che chiamerà Start() sul timer. Quando ciò, accade, sarà eseguito questa riga di codice:

this._dispatcher.AddTimer(this); 

E ora il Dispatcher si fa il tifo il timer, il che significa che non può essere GCed.

4

Timers sono un po 'particolare in quanto essi stessi radice chiamando

this.timerRoot = GCHandle.Alloc(this); 

alcuni link

EDIT:

non si erano accorti che era un DispatcherTimer - che non radicarsi direttamente, ma indirettamente (per il Dispatcher), che a sua volta conduce nello stesso senso ...

+0

Questo è in realtà sbagliato ... è un diverso tipo di timer. – dlev

+0

I DispatcherTimer sono soggetti alle stesse regole di garbage collection di Threading.Timers? In tal caso, non avere un riferimento di campo (solo un riferimento locale) al timer causerebbe la garbage collection in sé e per sé ... ma non penso che sia il caso di DispatcherTimers ... – Jeff

+0

@ JeffN825 Tutti gli oggetti sono soggetti a le stesse regole del GC: se sei irraggiungibile da una radice GC, allora sei idoneo per GC. In questo caso, quel codice non è nemmeno * da * la corretta classe del timer. – dlev

1

Sarà aggiunto alla coda Dispatcher che verrà rootata.