Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 11
  1. #1

    Eccezione in thread causa loop infinito

    Ciao a tutti. Ho uno strano problema... magari è una scemenza ma non riesco a capirci niente.
    Ho un processo che lancia una serie di thread worker in parallelo, che lavorano su dati disgiunti. Dopo che li ha lanciati tutti, fa una join su ciascuno per aspettare che terminino. Fin qui tutto bene. Il problema è che se viene lanciata una eccezione in un thread, il metodo che l'ha lanciata viene richiamato all'infinito, senza che ci sia alcun loop nel mio codice e senza che l'esecuzione passi di nuovo dalla chiamata.

    codice:
    //thread principale
    foreach (var item in myList)
    {
        Worker pm = new Worker(item);
        Thread t = new Thread(pm.Execute);
        threadList.Add(t);
        t.Start();
    }
    Il codice della execute è
    codice:
            public void Execute()
            {
    #if DEBUG
                System.Console.WriteLine(string.Format("worker {0}", item));
    #endif
                // Chiamata a metodo business di una dll
                Business.DoWork(item);
            }
    Per test nella DoWork ho messo solo una throw Exception(). Per qualche oscura ragione, quella eccezione viene lanciata senza sosta una volta dopo l'altra, senza che il codice passi di nuovo dalla chiamata Business.DoWork(item). Il thread avendo una eccezione, non dovrebbe terminare?

    Spero davvero che mi sappiate dare qualche suggerimento, ci sto impazzendo. Grazie.
    GreyFox (Linux registered user #435102)
    greyfox.imente.org - GreyFox's shots (photo gallery)
    $ cd /pub
    $ more beer

  2. #2
    Non ho idea del perché, ma se metto un try { ... } catch(Exception) { } nella Execute, allora tutto funziona come mi aspettavo... il mistero si infittisce
    GreyFox (Linux registered user #435102)
    greyfox.imente.org - GreyFox's shots (photo gallery)
    $ cd /pub
    $ more beer

  3. #3
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Vorrei capire come fai a fare il .Join su ciascun Thread, mostra il codice.

    ..... il metodo che l'ha lanciata viene richiamato all'infinito,
    quale metodo ??
    Sbagliare è umano, perseverare è diabolico.

  4. #4
    Non è quello il problema, la causa è una gestione delle eccezioni nei thread da parte di c# che mi sfugge del tutto

    Comunque è un semplice foreach (Thread t in threadList) t.Join();
    GreyFox (Linux registered user #435102)
    greyfox.imente.org - GreyFox's shots (photo gallery)
    $ cd /pub
    $ more beer

  5. #5
    Originariamente inviato da Pirelli72
    quale metodo ??
    In effetti ho scoperto che non è il metodo DoWork() ad essere richiamato, ma è la singola istruzione throw. Se entro in debugging mi ferma sulla throw come di consueto, ma se faccio F5 continua a mostrarmi all'infinito quella eccezione, senza più procedere in alcun modo nell'esecuzione.
    Non so quale sia il motivo (mi piacerebbe saperlo) ma quel try catch che ho messo al quale ho accennato nel post precedente ha risolto la questione: ora quando arriva al throw, questo finalmente causa la terminazione del thread e l'esecuzione procede correttamente con la join.
    GreyFox (Linux registered user #435102)
    greyfox.imente.org - GreyFox's shots (photo gallery)
    $ cd /pub
    $ more beer

  6. #6
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    Non ho ancora capito bene il tuo scenario, perdonami. Allora tu hai costruito una Classe Worker che espone il metodo [i].Execute[/b] che a sua volta richiama un metodo di una dll ?.
    Hai una lista di....qualcosa e per ogni .Item della lista crei un'istanza della classe Worker e lanci il suo metodo in un Thread separato.

    Generalmente io quando devo lavorare su più thread tendenzialmente creo una matrice di Thread cosa che potrebbe innanzitutto risparmiarti di popolare una lista ulteriore di Thread su cui interrogare il Join. Ma ovviamente il risultato è pressoché uguale.

    ......effetti ho scoperto che non è il metodo DoWork() ad essere richiamato, ma è la singola istruzione throw. Se entro in debugging mi ferma sulla throw come di consueto
    Cosa fa il metodo .Dowork col parametro Item ?
    Sbagliare è umano, perseverare è diabolico.

  7. #7
    Per chiarire ti incollo il codice completo di un modellino che ho fatto per riprodurre il problema. La lista di thread non c'entra, lo fa anche solo con uno.


    codice:
    namespace ThreadingProject
    {
        public class Worker
        {
            public string Name { get; set; }
    
            public Worker(string name)
            {
                Name = name;
            }
    
            public void Execute()
            {
                try
                {
                    System.Console.WriteLine(Name);
                    throw new Exception();
                }
                catch (Exception e)
                {
                    System.Console.WriteLine(e.ToString());
                }
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                Worker w = new Worker("pippo");
                Thread t = new Thread(w.Execute);
                t.Start();
                t.Join();
                System.Console.WriteLine("End");
                System.Console.ReadLine();
            }
        }
    }
    Questo codice funziona correttamente. Se togli il try catch però, vedi che l'esecuzione del thread si blocca sulla throw e non va più avanti, e quindi il Join() aspetta in eterno.
    GreyFox (Linux registered user #435102)
    greyfox.imente.org - GreyFox's shots (photo gallery)
    $ cd /pub
    $ more beer

  8. #8
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    E' tutto normale, non gestire le eccezioni sui Thread si va incontro a uno stato di congelamento dell'applicazione. Le eccezioni devono sempre essere gestite tramite il blocco Try....Catch, ma considerando che a sua volta anche il codice all'interno del blocco catch può sollevare un'eccezione, se tale blocco sta lavorando in un thread separato da quello del chiamante si può verificare lo stesso il congelamento dell'applicazione.
    Per cui bisogna intervenire in un'altro modo.
    Sbagliare è umano, perseverare è diabolico.

  9. #9
    Ottimo grazie, confermi quelli che erano solo miei sospetti. Ti ringrazio del link, molto utile da sapere per il futuro. Per questa applicazione comunque non mi serve, perché tanto il blocco catch lo lascio vuoto per far si che in caso di eccezione il thread termini.
    GreyFox (Linux registered user #435102)
    greyfox.imente.org - GreyFox's shots (photo gallery)
    $ cd /pub
    $ more beer

  10. #10
    Utente di HTML.it
    Registrato dal
    Apr 2009
    Messaggi
    970
    In ogni caso, riprendendo il discorso dei Thread, mi sento di consigliarti questo codice in sostituzione del tuo anche se la sintassi del codice che hai scritto risulta corretta.

    codice:
    {
    	System.Threading.Thread[] task = new System.Threading.Thread[11];
    	for (int w = 0; w <= 10; w++) {
    		task[w] = new System.Threading.Thread(Dowork);
    		task[w].Name = string.Concat("Thread", w);
    		task[w].IsBackground = true;
    		task[w].Start();
    	}
    
    	foreach (System.Threading.Thread thread in task) {
    		thread.Join();
    	}
    }
    Sbagliare è umano, perseverare è diabolico.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.