Come terminare un thread in C# e vivere felici

Il nostro viaggio del meraviglioso mondo dei thread continua. Adesso è il momento di vedere come terminare un thread. Ci sono due modi: uno grezzo, rozzo e brutale ed un altro più gentile (“Caro thread, per favore suicidati”).

Vediamo prima il metodo brutale.

Come terminare un thread in C# in modo brutale

Questo è il metodo più semplice di tutti: si chiama il metodo Abort nel thread target e questo termina:

using System;
using System.Threading;

namespace EsempiThread
{
    public class TerminazioneBrutale : IEsempio
    {
        public void Run()
        {
            Thread t = new Thread(Worker);
            t.Start();
            Console.WriteLine("Sono il thread principale. Dormo un po' e poi commetto un threadicidio");
            Thread.Sleep(5000);
            t.Abort();
            t.Join();
            Console.WriteLine("Esecuzione terminata. Premere un tasto per continuare.");
            Console.ReadKey();
        }

        private void Worker()
        {
            try
            {
                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("Sono un thread qualunque. Faccio cose, vedo gente...");
                    Thread.Sleep(1000);
                }
            }
            catch(ThreadAbortException tae)
            {
                Console.WriteLine("Sono un thread qualunque. Qualcuno mi ha ucciso. Ciò è indisponente");
            }
            finally
            {
                Console.WriteLine("Sono un thread qualunque. Se avessi bisogno di fare testamento potrei farlo qui.");
            }
        }
    }
}

Questo modo di terminarli andrebbe evitato, a meno che non siamo veramente sicuri di ciò che stiamo facendo. Questo metodo viene chiamato da un altro thread, diverso dal target, e quindi la terminazione può avvenire in qualsiasi momento. Capite da voi che il rischio di lasciare uno stato inconsistente è molto, molto alto.
Proprio per dare la possibilità al thread target di gestire questa situazione si fa in modo che esso sollevi una ThreadAbortException.
Se tutto questo vi è sembrato troppo crudele (e io me lo auguro) nei confronti del povero thread target consolatevi: esiste un metodo più gentile per terminare un thread.

Come terminare un thread in C# con gentilezza

Questo si chiama anche “metodo corretto per terminare un thread”. Si tratta in breve di usare un flag che dice al thread “Caro thread, fermati”:

using System;
using System.Threading;

namespace EsempiThread
{
    class TerminazioneGentile:IEsempio
    {
        public void Run()
        {
            bool deviFermarti = false;
            Thread t = new Thread(new ThreadStart(() =>
            {
                Worker(ref deviFermarti);
            }));
            t.Start();
            Console.WriteLine("Premi un tasto qualunque per terminare il worker thread.");
            Console.ReadKey();
            deviFermarti = true;
            Console.WriteLine(deviFermarti);
            t.Join();
            Console.WriteLine("Esecuzione terminata. Premere un tasto per continuare.");
            Console.ReadKey();
        }

        private static void Worker(ref bool deviFermarti)
        {
            while (!deviFermarti)
            {
                Console.WriteLine("Faccio cose, vedo gente...{0}",deviFermarti);
                Thread.Sleep(1000);
            }
            Console.WriteLine("Mi hanno detto che devo fermarmi e io obbedisco perché sono un bravo thread.");
        }
        
    }
}

La differenza sostanziale con il metodo precedente è che qui il thread target sa che si deve fermare, e ha tutto il tempo per sistemare le sue cose, fare testamento e suicidarsi.

In conclusione

Questo è pur sempre un esempio giocattolo, magari in un contesto reale non abbiamo un worker method che cicla finché qualcuno non gli dice “fermati”, e quindi bisognerà controllare periodicamente questa situazione.

Trovate il codice dell’esempio nel mio <a href=”https://github.com/dottorp/pierpaoloparis.it”>repository GitHub</a>.

Se l’articolo vi è piaciuto non esitate a contattarmi sui miei profili social (trovate i link qui accanto) oppure, se preferite, offritemi un caffè (chi mi conosce sa che sono un caffeinomane).

Pierpaolo Paris

Sono uno dei tanti che sono entrati nel girone infernale di Ingegneria Informatica, e che poi ne è anche uscito. Attualmente lavoro come sviluppatore presso una società di consulenza. Ogni tanto mi diletto con la fotografia.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *