Thread da terminare

di il
6 risposte

Thread da terminare

Ciao a tutti ragazzi, ho un problema che mi trovo ad affrontare per la prima volta.
Ho una lista di thread, dalla quale secondo la mia logica devo abortire, togliere un thread specifico. Il codice è:

if (searchThread.Count() > 0)
   {
    foreach (Thread toDelete in taskList.Where(y => y.Name != null && y.Name.Equals(msgToSend.Name)))
     {
         toDelete.Abort();
     }

 }
Se insomma trovo un thread con il nome che dico io faccio la Abort().
Ho provato a usare la Suspend(), ma così facendo poi i thread rimangono appesi e anche se chiudo l'applicazione visual studio continua a runnare.
Con l'abort() avrei risolto, ma di default ho letto che è normale venga lanciata un' eccezione di tipo: System.Threading.ThreadAbortException.
Qual è il metodo giusto per killare i thread senza avere eccezioni?

Grazie

6 Risposte

  • Re: Thread da terminare

    Devi interromperne il funzionamento.

    Supponi di avere un ciclo in cui viene eseguito il thread. Tale ciclo deve essere controllato da una variabile inizialmente a true. Quando la imposti a False, il ciclo termina e il thread finisce naturalmente.
  • Re: Thread da terminare

    Ok, fin qui ti seguo, sbaglio qualcosa allora, dunque questo è il codice eseguito dal thread:
    c'è il while true che esegue fin che nono arriva il token di ritorno.
    
    public void SendCyclicMessage(Message message, CancellationToken cancelToken)
            {
                try
                {
                    XLDefine.XL_Status txStatus;
                    XLClass.xl_event_collection xlEventCollection = new XLClass.xl_event_collection(1);
                    xlEventCollection.xlEvent[0].tagData.can_Msg.id = message.Id;
                    xlEventCollection.xlEvent[0].tagData.can_Msg.dlc = message.Dlc;
                    xlEventCollection.xlEvent[0].tagData.can_Msg.id = message.Id;
                    xlEventCollection.xlEvent[0].tagData.can_Msg.dlc = message.Dlc;
    
                    for (int i = 0; i < message.Dlc; ++i)
                    {
                        xlEventCollection.xlEvent[0].tagData.can_Msg.data[i] = message.Bytes[i];
                    }
    
                    xlEventCollection.xlEvent[0].tag = XLDefine.XL_EventTags.XL_TRANSMIT_MSG;
    
                    while (true)
                    {
                        // Transmit events on txMask = Channel 
                        txStatus = CANDriver.XL_CanTransmit(portHandle, accessMask, xlEventCollection);
                        Thread.Sleep(message.CycleTime);
    
                        if (txStatus != 0)
                        {
                            Console.WriteLine("Message transmission failed!", "Error Message");
    
                        }
    
                        if (cancelToken.IsCancellationRequested) //cancel token sended to stop thread
                        {
                            return;
                        }
                    }
                }
    
                catch (Exception ex)
                {
                    // return;
                    Console.WriteLine("Error from method: " + "sendCyclicMessage: " + ex.Message);
                }
    
            }
    
    Per farlo partire, da un'altra classe, inizializzo il token:

    
        CancellationTokenSource tokenSource = new CancellationTokenSource();
                    CancellationToken CancellationToken = tokenSource.Token;
    
    poi faccio partire il thread sempre dalla classe dove ho creato il token:
    
     taskList.Add(new Thread(() => vector.SendCyclicMessage(msgToSend, CancellationToken)));
                                    taskList.Last().Name = msgToSend.Name;
                                    taskList.Last().Start();
    
    poi in fondo alla sezione quando ho finito:
    
     tokenSource.Cancel(); //KILL ALL THREADS AND LIST
    
    Ma mi restano in pending........
  • Re: Thread da terminare

    Ciao

    E' normale che venga scatenata l'eccezione, poiche' e' una condizione anomala che non dovrebbe essere utilizzata.
    Nel tuo codice, ad esempio, vedo che passi al Thread un cancellation token.
    Perche' non usi quello per terminare il thread?

    In pratica, nei punti "safe" del thread, controlli se il cancellation token richiede di uscire. In tal caso esci in modo "sicuro", ovvero rilasciando tutte le risorse necessarie.
    Nel gestore, anziche' chiamare l'abort, imposti la richiesta di sospendere il thread tramite cancellation token


    PS: Solo per curiosita', hai valutato se nella tua realta' convenga usare dei thread piuttosto che dei task?
  • Re: Thread da terminare

    Mh ok provo subito, il fatto è che credo con quell'istruzione vengano stoppati tutti i thread e non solo uno, perchè il token source è settato su altri thread.
    Onestamente non ho valuto i task, ho letto che dovrebbero essere più efficienti. Garantiscono il parallelismo? Perchè ho dei messaggi periodici su un bus che devono restare attivi. Scusa non sono molto ferrato.
  • Re: Thread da terminare

    Se ricordo bene parallellismo, thread e task sono cose diverse fra loro.

    Ad esempio, se hai un unico processore, puoi far partire quanti thread/task vuoi, però saranno sempre in sequenziale e mai in parallelo, poichè il processore è unico e quindi non può fare due elaborazioni in contemporanea.

    Se vuoi lavorare in parallelo (ammesso che il sistema possa farlo), esistono le apposite classi e metodologie di lavoro (con tanto di permessi di accesso alle variabili in contemporanea + errori vari che possono saltar fuori). Se cerchi su Google con "C# parallel programming" trovi una valanga di articoli/esempi


    Quanto all'uso dei task, se usi lo stesso cancellation token per tutti i task, allora concordo con te che per stopparne uno li stoppi tutti.

    Nessuno ti vieta però di generare un cancellation token per ogni task e quindi usare quello. Comunque se cerchi la documentazione per CancellationTokenSource e CancellationToken trovi un po' tutti gli esempi del caso
  • Re: Thread da terminare

    Perfetto, grazie mille. Considero chiuso l'argomento.
Devi accedere o registrarti per scrivere nel forum
6 risposte