Autore Topic: La funzione join rimane appesa anche se non dovrebbe  (Letto 1264 volte)

Offline Giacomo79

  • Utente junior
  • **
  • Post: 123
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    Big and Fish
  • Sistema operativo:
    Android 2.3
La funzione join rimane appesa anche se non dovrebbe
« il: 09 Dicembre 2013, 17:08:57 CET »
0
Salve a tutti, non capisco perché la funzione join su un thread rimane appesa anche se non dovrebbe. Questo è il codice del Thread all'interno di una Surface:
Codice (Java): [Seleziona]
class MainThread extends Thread {
                private SurfaceHolder sh;
                private SurfaceEndQuestion surface;

                private Canvas canvas;

                private boolean run = false;

                public MainThread(SurfaceHolder _holder, SurfaceEndQuestion _surface) {
                    sh = _holder;
                    surface = _surface;
                }

                public void setRunnable(boolean _run) {
                    run = _run;
                }

                public void run() {
                    while(run) {
                        canvas = null;
                        try {
                            canvas = sh.lockCanvas(null);
                            synchronized(sh) {
                                surface.onDraw(canvas);
                            }
                        } finally {
                            if(canvas != null) {
                                sh.unlockCanvasAndPost(canvas);
                            }
                        }
                    }
                }

                public Canvas getCanvas() {
                    if(canvas != null) {
                        return canvas;
                    } else {
                        return null;
                    }
                }
        }
E questa è la funzione dove fermo il thread e dove l'applicazione rimane appesa:
Codice (Java): [Seleziona]
private void Stop() {
        if (mainThread != null) {
                    boolean retry = true;
                    mainThread.setRunnable(false);
       
                    while(retry) {
                        try {
                            mainThread.join();
                            retry = false;
                        } catch(InterruptedException ie) {
                            //Try again and again and again
                        }
                        break;
                    }
                }

            mainThread = null;
    }
Sapete perché? Setto a false la variabile interno del thread, che quindi dovrebbe chiudersi correttamente.

Grazie

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #1 il: 09 Dicembre 2013, 17:14:53 CET »
0
A occhio non vedo niente di strano.
Metti un po' di Log.d() nei punti cruciali di entrambi i Thread, così vedo dove passa e dove non passa l'esecuzione.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Giacomo79

  • Utente junior
  • **
  • Post: 123
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    Big and Fish
  • Sistema operativo:
    Android 2.3
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #2 il: 09 Dicembre 2013, 17:39:41 CET »
0
Non noto niente di strano con il Log. Setta a false la variabile del Thread, e poi si pianta sul join. Non arriva mai all'istruzione successiva.

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #3 il: 09 Dicembre 2013, 17:44:16 CET »
0
Non noto niente di strano con il Log. Setta a false la variabile del Thread, e poi si pianta sul join. Non arriva mai all'istruzione successiva.

Si ma il MainThread cosa sta facendo?
Continua ad iterare il while(run) anche se run è false ? (sarebbe un miracolo)
Non è che a sua volta è bloccato da qualche parte e non ripassa da while(run) ? (da provare con i Log)
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Giacomo79

  • Utente junior
  • **
  • Post: 123
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    Big and Fish
  • Sistema operativo:
    Android 2.3
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #4 il: 09 Dicembre 2013, 18:19:15 CET »
0
Si ma il MainThread cosa sta facendo?
Continua ad iterare il while(run) anche se run è false ? (sarebbe un miracolo)
Non è che a sua volta è bloccato da qualche parte e non ripassa da while(run) ? (da provare con i Log)
Ho qualche info in più. Quando si blocca poi non entra nel run.
Però ho notato che se all'interno della funzione OnDraw della Surface setto a false la variabile del Thread, tutto funziona bene.
Se la variabile del Thread non la setto dalla funzione OnDraw ma dalla funzione surfaceDestroyed, il sistema si blocca sulla join. Perché? La surfaceDestroyed non viene chiamata durante l'onPause dell'Activity?

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #5 il: 10 Dicembre 2013, 16:04:21 CET »
0
Questo è un "pattern" molto usato in rete per la creazione di giochi in android, l'ho visto spesso in tutorial e anche su alcuni libri che trattano l'argomento. Personalmente non mi piace molto l'uso del join all'interno di un loop while, e di fatti secondo me questa tecnica viene usata per ovviare all'eccezione ANR di android. Probabilmente il tuo join si "pianta" perchè viene generata una eccezione InterruptedException all'interno del while che esegue il join, e questo accade perchè il thread in attesa della fine dell'altro thread (quello che aggiorna la grafica del SurfaceView), viene bloccato a sua volta. In pratica, se all'interno dell'onPause dell'Activity viene chiamato il join, il thread dell'Activity viene messo in attesa, ma dato che l'Activity viene bloccata a sua volta dal sistema (lo si capisce meglio se si ha sott'occhio il lifecycle dell'Activity  ;-)) si genera l'eccezione InterruptedException. Questa è una mia supposizione, poichè non ho visto tutto il tuo codice e non so come e dove chiami il join, ma puoi provare a stampare in console lo stackTrace all'interno del catch per vedere se ti capita quello che ho descritto. In conclusione quello che si vuole "provocare" con questo pattern è proprio quello di "appendere" il thread, generando eccezioni su eccezioni...funziona ma è un po brutto !
« Ultima modifica: 10 Dicembre 2013, 16:10:47 CET da teskio »

Offline Giacomo79

  • Utente junior
  • **
  • Post: 123
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    Big and Fish
  • Sistema operativo:
    Android 2.3
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #6 il: 10 Dicembre 2013, 19:24:02 CET »
0
L'errore sta nel OnDraw, dove l'oggetto canvas è vuoto. Mi è bastato inserire un try catch nella funzione e il problema non si presenta.
Però rimane il discorso riguardo al join all'interno del ciclo while. Come si può fare diversamente? Basta togliere il ciclo?

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #7 il: 11 Dicembre 2013, 15:27:44 CET »
0
E no il ciclo lo devi lasciare ! Sta proprio lì il trucco !  ;-)
O inventi qualcosa di completamente diverso, o lasci tutto così com'è.

Offline Giacomo79

  • Utente junior
  • **
  • Post: 123
  • Respect: 0
    • Mostra profilo
  • Dispositivo Android:
    Google Nexus One
  • Play Store ID:
    Big and Fish
  • Sistema operativo:
    Android 2.3
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #8 il: 11 Dicembre 2013, 15:44:12 CET »
0
E no il ciclo lo devi lasciare ! Sta proprio lì il trucco !  ;-)
O inventi qualcosa di completamente diverso, o lasci tutto così com'è.
Allora non ho capito la tua osservazione sul pattern brutto .... :-)

Offline teskio

  • Moderatore globale
  • Utente normale
  • *****
  • Post: 387
  • Respect: +118
    • Github
    • Google+
    • Mostra profilo
    • Skullab
  • Dispositivo Android:
    Cubot GT99 / SurfTab Ventos 10.1
  • Play Store ID:
    Skullab Software
  • Sistema operativo:
    windows 7 / ubuntu 12.04
Re:La funzione join rimane appesa anche se non dovrebbe
« Risposta #9 il: 11 Dicembre 2013, 15:54:46 CET »
0
Era una osservazione personale  :-) , per me è un po brutto, nel senso che vengono sollevate ciclicamente delle eccezioni. In un libro che ho, viene mostrato l'esempio che stai implementando, la spiegazione di quelle righe di codice è :
Citazione
...This method will wait for the thread to die, but might throw an InterruptedException before the thread actually dies.Since we have to make absolutely sure that the thread is dead before we return from that method, we perform the join in an endless loop until it is successful.