Perche non hai fatto quello che ti avevo chiesto di fare, ragionare.
Ti riporto la dicitura che descrive il metodo Abort.
Viene generata un'eccezione ThreadAbortException nel thread in cui viene richiamato, per iniziare il processo di terminazione del thread. La chiamata a questo metodo determina in genere la fine del thread.
Abort non termina il thread, forse non è cosi chiaro; ma come scritto sopra Abort genere un eccezione nel thread che andrà gestita.
msdn.microsoft.com/it-it/library/…
Quello che ho cercato (aggiungerei inutilmente) di farti capire nel post precedente è come si dovrebbe comportare il thread. il thread va a chiudersi automaticamente quando viene completato, l'eccezione scaturita da Abort se gestita dovrebbe fare in modo che il metodo giunga alla fine della sua vita.
Ora voglio riprovare a farti capire quello che ti ho spiegato in precedenza, presta attenzione.
Mettiamo che tu abbia una classe
public class A {
static public bool x = true;
static public void TH()
{
while(A.x) {
Sleep(1000);
}
}
}
Come vedi se avvio un nuovo thread con metodo TH() questo continuerà a loop il while e di conseguenza lo Sleep all'interno che simula un operazione dispendiosa in termini di calcolo. Ora se voglio andare a terminare il thread andrò ad agire sulla variabile statica x che non si trova direttamente dentro il thread generato anche se questo puo accedervi, in questo modo appena porterò x a false il thread
finirà il ciclo corrente di while e poi ne uscirà. x essendo publico puo essere modificato da qualsiasi punto dell'applicazione padre, quindi capisci che la tua procurazione non è fondata, io posso terminare il thread da ogni posizione nel codice anche dall'interno di un ipotetica classe B.
Spero di averti fatto capire il procedimento.
Ora visto che hai tirato in causa Abort voglio che tu capisca perché è da preferirsi la soluzione di prima a questo metodo.
prendiamo di nuovo la classe A e modifichiamo TH perché gestisca Abort.
static public void TH()
{
try {
while(true) {
Sleep(1000);
Save();
}
} catch(ThreadAbortException ex) {
Console.Write("Il thread termina");
}
}
Ok allora vediamo un po le modifiche apportate, abbiamo inserito un blocco try con un catch sull'eccezione
ThreadAbortException quando chiameremo Abort l'eccezione verrà lanciata e indipendentemente dallo stato di esecuzione di TH si andrà ad eseguire il write, fatto questo il thread si concluderà, sembra tutto ok ma vediamo un caso particolare, prendiamo che Sleep sia la simulazione di un calcolo oneroso e necessario per il sostentamento dell'applicazione e che ogni volta che questo viene concluso Save salvi il risultato per il thread principale, mettiamo ora che il flusso di esecuzione vada a trovarsi in mezzo a sleep e save mentre viene a verificarsi l'eccezione, cosa succederebbe? Ovviamente il calcolo è finito e il risultato andrebbe salvato ma questo non accade perche il flusso di esecuzione va a spostarsi sul write facendo in modo che save non venga eseguito. Nella maggior parti dei casi quando si usa il metodo abort bisognerebbe aggiungere al blocco try un blocco finaly che si occupi di gestire lo stato in cui si trova il metodo quando viene a generarsi l'eccezione, proprio per andare a colmare i problemi che causa questa interruzione improvvisa. Credo tu possa capire ora perche è consigliabile il primo metodo che permette alla funzione di concludersi in modo naturale senza lanciare eccezioni, che se non vengono gestite andranno a creare problemi ad un livello piu basso nel tuo caso alla GUI.
Spero di essere stato il più esplicativo possibile, cerca di riflettere sempre su tutte le implicazioni che comporta una determina tecnica e perché te ne venga suggerita un altra, è giusto non fidarsi alla cieca ma dopo lo scetticismo va applicata un acuta riflessione e non un salto della fede verso un metodo a caso :P