Autore Topic: Thread, AsyncTask o Service per esecuzione di task  (Letto 2202 volte)

Offline alexAndroid

  • Utente normale
  • ***
  • Post: 185
  • Respect: +27
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Giò
  • Sistema operativo:
    Ubuntu 11.10; Windows XP
Thread, AsyncTask o Service per esecuzione di task
« il: 27 Febbraio 2012, 09:36:17 CET »
0
Salve a tutti,
nel progettare la mia applicazione mi sono incagliato in un serio problema. In breve ciò che devo fare è eseguire 5 Task (o processi lavorativi) in maniera sequenziale. La sequenza di azioni è più o meno questa:
1) Premo un bottone, il thread main lancia il  task1
2) Il thread main "deve rimanere in attesa" della fine del task1 senza fare niente; poi lancia il task2
3) Il Thread Main rimane in attesa ed al termine del task2 lancia il task3.
4) Il Thread Main rimane in attesa ed al termine del task3 lancia il task4.
5) Il Thread Main rimane in attesa ed al termine del task4 lancia il task5.
6) Arresto dei processi ed eventuale "riciclo" dei passaggi precedenti.

Dove è scritto "deve rimanere in attesa" significa che il main non deve rimanere bloccato (applicazione non risponde), ma deve rimanere fermo fino ad una eventuale chiamata di ritorno del thread che ha finito il lavoro.

Per prima cosa mi sono buttato sugli AsyncTask che mi sono molto comodi per la visualizzazione di ProgressBar. Ma devo ancora capire se il thread main può mai accorgersi di quando finisce l'asynctask lanciato.
Sei stato aiutato oppure il tuo problema è stato risolto? Allora premi il tasto THANKS E' un modo utile e carino per ringraziare chi ti è stato di aiuto.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #1 il: 27 Febbraio 2012, 10:08:38 CET »
0
Io se fosse possibile proverei ad affrontare il problema da un punto di vista diverso.
Non tanto il "sapere se il task ha finito" ma porre una condizione che mette l'activity in uno stato particolare se il task è in esecuzione.

Per esempio ti dichiari un bool m_bTaskRunning, lo setti true quando il task parte e lo fai resettare false dal task quando ha finito.
In questo modo puoi gestire il comportamento dell'activity mentre il task è in esecuzione a tuo piacimento.

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:Thread, AsyncTask o Service per esecuzione di task
« Risposta #2 il: 27 Febbraio 2012, 10:48:09 CET »
+1
Più che "accorgersi", fai in modo che il thread secondario invii un messaggio al thread principale una volta che ha finito.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline alexAndroid

  • Utente normale
  • ***
  • Post: 185
  • Respect: +27
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Giò
  • Sistema operativo:
    Ubuntu 11.10; Windows XP
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #3 il: 27 Febbraio 2012, 11:39:49 CET »
0
Per esempio ti dichiari un bool m_bTaskRunning, lo setti true quando il task parte e lo fai resettare false dal task quando ha finito.
In questo modo puoi gestire il comportamento dell'activity mentre il task è in esecuzione a tuo piacimento.

Questo ragionamento ho cercato di adattarlo già per gli asynctask. Ovvero il main controllava se il task.getStatus() ritornava "FINISHED" oppure "RUNNING". Il problema è che il controllo posso effettuarlo solo una volta, ti mostro un esempio pratico con il booleano cui mi dicevi:
Codice (Java): [Seleziona]
// Nel Main onCreate()
Button btnAvvia = (Button) findViewById(R.idButton.startWork);
        btnAvvia.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                boolean m_bTaskRunning = true;
                                TaskAsync taskAsync = new TaskAsync();
                                taskAsync.execute("");
                                if (m_bTaskRunning == false)
                                     taskAsync2.execute("");
                        }
                });

// Nell'AsyncTask
 @Override
        protected void onPostExecute(String unused) {
                dismissDialog(DIALOG);
                m_bTaskRunning = false;        
        }

Tralasciando il fatto che m_bTaskRunning scritto in questo modo non è visibile all'AsyncTask, il problema è un altro.
Nel momento in cui viene eseguito AsyncTask.execute(""), viene lanciato il thread asincrono che agisce in maniera indipendente.
Il main a sua volta prosegue la sua esecuzione, eseguendo il controllo del booleano che troverà sicuramente = true perchè asynctask non può aver finito. Quello che voglio dirti è: come faccio a ricontrollare il booleano finchè non ha finito???

Più che "accorgersi", fai in modo che il thread secondario invii un messaggio al thread principale una volta che ha finito.

In questo caso dovrei utilizzare l'approccio dei Thread con rispettivi handler e message??? Vorrei se possibile, provare ad avere una soluzione comoda con gli AsyncTask
Sei stato aiutato oppure il tuo problema è stato risolto? Allora premi il tasto THANKS E' un modo utile e carino per ringraziare chi ti è stato di aiuto.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #4 il: 27 Febbraio 2012, 11:52:43 CET »
+1
Capisco il problema, ma vorrei scinderlo in due parti. Una parte è l'esecuzione della "catena di task", l'altro è sapere quando la "catena di task" è terminata.

Quello che intendo io è utilizzare un approccio "alternativo" al problema.
Spostare il problema da "controllare quando finisce il tuo task" a "controllare se è in esecuzione".

Poichè la tua activity per ovvie ragioni deve rimanere "attiva", si suppone che l'utente ci possa interagire in qualche modo.

Se hai un bottone che ha un comportamento diverso (per esempio deve essere disabilitato se hai la catena di task in esecuzione), invece di attivarlo/disattivarlo quando il task ha finito semplicemente quando viene premuto tu controlli se il task è in esecuzione, se lo è non fai niente o segnali all'utente che il task è in esecuzione.

Per quanto riguarda la catena di task dipende da quanto vuoi che sia flessibile, in teoria potresti fare un thread/task che gestisce una serie di task. Cioè ti crei un task che continua a girare fino a quando gli asynctask non sono stati tutti eseguiti e si occupa di gestire la loro esecuzione sequenziale. Questo pattern si adatta bene a quello che hai scritto nel primo post.

Offline alexAndroid

  • Utente normale
  • ***
  • Post: 185
  • Respect: +27
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Giò
  • Sistema operativo:
    Ubuntu 11.10; Windows XP
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #5 il: 27 Febbraio 2012, 12:11:39 CET »
0
Giustappunto che parli di Pattern era proprio quello a cui puntavo di fare.
Ti parlo un pochino di più della mia applicazione. Per adesso è formata da varie classi e una sola activity con 2 pulsanti: start e stop. La mia applicazione deve lavorare in maniera automatica dopo la pressione del tasto start. Al più verranno eseguiti 6 task. Però io vorrei che il programma di esecuzione dei task non sia statico (ovvero task1 poi task2 poi task3...), ma che possa variare dinamicamente (ad esempio cambiando un file di configurazione esterno).
Detto questo vorrei che il Thread Main fungesse da MEDIATOR tra i vari task (decide chi fa partire e quando) ed insieme a TEMPLATE METHODS e STRATEGY potesse decidere anche quale piano di task eseguire.

Pensi che sia necessario delegare ad un altro thread il lavoro di mediator? Quindi il main non dovrà fare assolutamente niente.
Sei stato aiutato oppure il tuo problema è stato risolto? Allora premi il tasto THANKS E' un modo utile e carino per ringraziare chi ti è stato di aiuto.

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:Thread, AsyncTask o Service per esecuzione di task
« Risposta #6 il: 27 Febbraio 2012, 12:26:23 CET »
+1
In questo caso dovrei utilizzare l'approccio dei Thread con rispettivi handler e message??? Vorrei se possibile, provare ad avere una soluzione comoda con gli AsyncTask

Puoi inviare messaggi anche da un AsyncTask, nessuno te lo vieta.

Altra soluzione, più semplice, ma (molto) più grezza potrebbe essere sfruttare il fatto che la PostExecute dell'AsyncTask gira nel thread main: potresti quindi richiamare direttamente una funzione membro dell'activity principale che si occupa di gestire i task. Detto in altre parole, la PostExecute è come se fosse l'handler che gestisce il messaggio di fine task.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #7 il: 27 Febbraio 2012, 12:29:27 CET »
+1
Allora... a meno che tu non preveda un restart a metà (per esempio stai eseguendo il task numero 3 di 5 e vuoi interromperlo e ripartire dal primo con un click) ti consiglio di mettere un solo bottone start/stop (segnalando con una stringa lo stato corrente), per le seguenti ragioni:

1- è più intuitivo per l'utente finale
2- avere due bottoni è spesso inutile perchè non è logico il comportamento dello "start" di qualcosa che è già in esecuzione (se stai eseguendo il task3 che succede se premi start? nulla/riparte dal task 1/riparte dal task 3?) e lo stop di qualcosa che è già fermo non ha effetti.

In particolar modo mi interessa il punto uno. Da utente se faccio partire qualcosa con start poi start dovrebbe essere disattivato. E allo stesso modo se lo stoppo il bottone stop dovrebbe essere disattivato. Se non lo sono intuitivamente mi viene in mente che è possibile cliccarci sopra. Se ci clicco e non succede niente o il risultato è oscuro (tipo un restart) l'app non ci fa una bella figura secondo me.

Delegare il lavoro ad un altro thread è una soluzione logica sopratutto per la riusabilità. Però a questo punto potresti anche decidere di non legare il thread all'activity ma a un service. Ovvero crei un service e al suo interno crei il thread che a sua volta esegue i task. In questo modo potresti anche passare la stringa coi task nell'intent della startservice, parsarla e usare la reflection per crearti la catena di task.

 ;-)

Offline alexAndroid

  • Utente normale
  • ***
  • Post: 185
  • Respect: +27
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Giò
  • Sistema operativo:
    Ubuntu 11.10; Windows XP
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #8 il: 27 Febbraio 2012, 12:30:58 CET »
0
Altra soluzione, più semplice, ma (molto) più grezza potrebbe essere sfruttare il fatto che la PostExecute dell'AsyncTask gira nel thread main: potresti quindi richiamare direttamente una funzione membro dell'activity principale che si occupa di gestire i task. Detto in altre parole, la PostExecute è come se fosse l'handler che gestisce il messaggio di fine task.

Ti ringrazio per il suggerimento Bradipao. Ci avevo già pensato a questa scelta programmatica. E' una soluzione che sicuramente funziona, ma in questo modo legherei definitivamente il task1 al task2, il task2 al task3 e così via dicendo. Vorrei (come detto nel post precedente) una soluzione più flessibile dove chiamare un task a seconda del bisogno.
Sei stato aiutato oppure il tuo problema è stato risolto? Allora premi il tasto THANKS E' un modo utile e carino per ringraziare chi ti è stato di aiuto.

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:Thread, AsyncTask o Service per esecuzione di task
« Risposta #9 il: 27 Febbraio 2012, 12:55:41 CET »
0
Ti ringrazio per il suggerimento Bradipao. Ci avevo già pensato a questa scelta programmatica. E' una soluzione che sicuramente funziona, ma in questo modo legherei definitivamente il task1 al task2, il task2 al task3 e così via dicendo. Vorrei (come detto nel post precedente) una soluzione più flessibile dove chiamare un task a seconda del bisogno.

I task non devono essere legati. E' nella funzione membro che richiami che decidi la sequenza.
NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline alexAndroid

  • Utente normale
  • ***
  • Post: 185
  • Respect: +27
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Giò
  • Sistema operativo:
    Ubuntu 11.10; Windows XP
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #10 il: 20 Marzo 2012, 23:24:36 CET »
0
E' un pò di tempo che sono stato dietro a questo progetto. Poi è stato messo un pò da parte.
Ora spero di rispolverarlo un pochino e di concluderlo.
Fino ad ora ho realizzato all'interno di un'unica classe:
- il metodo che gestisce la sequenza dei task
- i 5 asyncTask che rappresentano i task da eseguire.

Tutto funziona in modo corretto come da programma. Però adesso quello che desidero fare è strutturare minimamente il codice.
Quindi vorrei separare i 5 asyncTask ognuno in una classe diversa; il metodo che controlla la sequenza vorrei metterlo in una classe CONTROLLER separata; ed infine avrei la MainActivity che è l'unica Activity dove appaiono le varie dialog di caricamento.
La domanda è: come faccio da una classe AsyncTask a far tornare il risultato alla classe Controller?
Sei stato aiutato oppure il tuo problema è stato risolto? Allora premi il tasto THANKS E' un modo utile e carino per ringraziare chi ti è stato di aiuto.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #11 il: 21 Marzo 2012, 10:38:34 CET »
+1
Passi il controller che controlla l'asynctask come parametro, poi nella postexecute ti chiami un metodo o setti una variabile o comunque lavori direttamente sul controller.  ;-)

Offline alexAndroid

  • Utente normale
  • ***
  • Post: 185
  • Respect: +27
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy Giò
  • Sistema operativo:
    Ubuntu 11.10; Windows XP
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #12 il: 21 Marzo 2012, 11:16:08 CET »
0
Ricapitolo:
- La mainActivity crea l'oggetto StrategyController.
- MainActivity lancia il metodo Controller.
- Il metodo Controller della classe StrategyController crea l'oggetto Task1
- Il metodo Controller esegue task1.execute passando come parametri delle stringhe (utili al mio fine) e se stesso (ovvero l'oggetto Strategy Controller)?
- Così nell'onpostExecute di task1 posso chiamare il metodo StrategyController.controller(valore ritorno).

Giusto? Mi sembra un'ottima soluzione. Vedo nei prossimi giorni di reimplementare tutto e ti faccio sapere
Sei stato aiutato oppure il tuo problema è stato risolto? Allora premi il tasto THANKS E' un modo utile e carino per ringraziare chi ti è stato di aiuto.

Offline undead

  • Utente senior
  • ****
  • Post: 666
  • Respect: +113
    • Mostra profilo
  • Dispositivo Android:
    Samsung Galaxy S6
  • Play Store ID:
    DrKappa
  • Sistema operativo:
    Windows 10 64-bit, Windows 8.1 64-bit
Re:Thread, AsyncTask o Service per esecuzione di task
« Risposta #13 il: 21 Marzo 2012, 11:33:34 CET »
0
Si esattamente. Poi potesti farti una tua interface "callback" e implementarla nel controller, comunque il principio è quello.  ;-)