2015-05-18 15 views
15

Ho semplificato l'esempio seguente per motivi di chiarezza, ma l'ho trovato in un programma di produzione dal vivo e non riesco a vedere come funzionerebbe!Cosa succede a un thread quando la classe originale esce dall'ambito

public class Test 
{ 
    static void Main() 
    { 
     Counter foo = new Counter(); 
     ThreadStart job = new ThreadStart(foo.Count); 
     Thread thread = new Thread(job); 
     thread.Start(); 
     Console.WriteLine("Main terminated"); 
    } 
} 

public class Counter 
{ 
    public void Count() 
    { 
     for (int i = 0; i < 10; i++) 
     { 
      Console.WriteLine("Other thread: {0}", i); 
      Thread.Sleep(500); 
     } 
     Console.WriteLine("Counter terminated"); 
    } 
} 

La routine principale avvia il thread contatore e termina la routine principale. Il contro thread continua indipendentemente dando il seguente output.

Main terminated  
Other thread: 0 
Other thread: 1 
Other thread: 2 
Other thread: 3 
Other thread: 4 
Other thread: 5 
Other thread: 6 
Other thread: 7  
Other thread: 8  
Other thread: 9 
Counter terminated 

Il mio programma di esempio dimostra che sebbene la classe chiamante non esista più, il thread sopravvive fino al completamento. Tuttavia, la mia comprensione è che una volta che una classe è fuori dal campo di applicazione, le sue risorse verranno riordinate alla fine dalla garbage collection.

Nel mio scenario di vita reale, il thread esegue un'e-mail di massa della durata di 1-2 ore. La mia domanda è "La raccolta di dati inutili può eventualmente eliminare il thread o GC sa che il thread è ancora in elaborazione"? Il mio thread di mailing è sempre in esecuzione o esiste un pericolo che si interrompa in modo anomalo?

+0

* Tuttavia, la mia comprensione è che una volta che una classe è fuori portata, le sue risorse saranno eventualmente riordinate dalla garbage collection. * I thread sono un caso speciale ... Portano gli oggetti 'Thread'" dentro "loro stessi, nel 'Thread.CurrentThread', ** e ** il loro metodo corrente è considerato come un GC Root (quindi un punto di partenza per il GC per scoprire se un oggetto ha ancora riferimenti) ... Ma sì, è un ragionamento circolare. – xanatos

+2

Le classi non escono dall'ambito. Gli oggetti non vanno oltre lo scopo. Le variabili escono dall'ambito di applicazione (che è facile da capire - tutto ciò significa che la variabile non esiste più. Se la variabile è un riferimento, non fa nulla all'oggetto a cui fa riferimento). – immibis

risposta

12

Da System.Threading.Thread

Non è necessario mantenere un riferimento a un oggetto Thread una volta che avete iniziato il filo. Il thread continua ad essere eseguito fino al termine della procedura thread.

Quindi, anche se l'oggetto Thread non è referenziato, il thread verrà comunque eseguito.

9

Dai un'occhiata alla documentazione per System.Threading.Thread.IsBackground

Se un thread non è un thread in background, manterrà l'applicazione dal spegnimento finché non è finito.

+0

IsBackground lo spiega.Quando l'ho impostato su true, il programma termina immediatamente come mi aspettavo. Grazie per avermi indicato nel posto giusto. – MortimerCat

+1

@MortimerCat Che non ha nulla a che fare con la garbage collection. È un comportamento completamente * separato *. L'oggetto su cui è in esecuzione il punto di ingresso del thread non viene raccolto, piuttosto l'intero processo viene rimosso perché non ci sono thread attivi. Questo non ha nulla a che fare con gli ambiti, il GC o qualsiasi oggetto; tutto ciò che conta è se ci sono thread in primo piano in esecuzione. – Servy

+0

Sì, @Servy ha fornito una spiegazione migliore alle tue domande sulla garbage collection; questa risposta è più su "come cambio questo comportamento inaspettato?" – adv12

8

Tuttavia, la mia comprensione è che una volta che una classe è fuori dal campo di applicazione, le sue risorse saranno eventualmente riordinate dalla garbage collection.

Questo può essere affermato più precisamente:

volta un'istanza oggetto non accessibile da qualsiasi codice eseguibile mediante un riferimento gestito è, diventa per la garbage collection.

Quando si crea un nuovo thread che esegue il metodo di un particolare oggetto, si rende accessibile il contenuto di quell'oggetto durante la vita di quel thread. Il GC può solo ripulirlo se è in grado di dimostrare che non è più possibile per nessuno dei thread dell'applicazione accedere nuovamente a quell'oggetto. Poiché il tuo codice può accedere a ancora all'istanza dell'oggetto, non riceve GCed.

Problemi correlati