Mi SwingWorker no se cancela

Iniciado por Zoik, 29 Agosto 2013, 10:07 AM

0 Miembros y 2 Visitantes están viendo este tema.

Zoik

Bien estoy puliendo una aplicación de shutdown y me e quedado atascado en un lugar.

Tengo el siguiente método que recoge los eventos de dos botones, cuando le doy a programar el apagado me inicia la variable time cogiendome los valores de tres JComboBox, time, es un SwingWorker que revisa la hora, supuestamente cuando yo le diese a cancelar, con el comando time.cancel(true) me tendría que detener el thread, pero no es así:

Código (java) [Seleccionar]
public void actionPerformed(ActionEvent evt) {
CheckTime time = new CheckTime(hour.getSelectedIndex(), min.getSelectedIndex(), sec.getSelectedIndex());
if(evt.getSource() == programShutdown && isStarted == false){
System.out.println("iniciado!");
time.execute();
isStarted = true;
} else if(evt.getSource() == cancelShutdown && isStarted == true){
System.out.println("cancelado!");
time.cancel(true);
isStarted = false;
}

}


Código (java) [Seleccionar]
package base;

import java.util.Calendar;

import javax.swing.SwingWorker;

public class CheckTime extends SwingWorker{
private int copyHour;
private int copyMin;
private int copySec;
public  CheckTime(int hour,int min, int sec){
copyHour = hour;
copyMin = min;
copySec = sec;
}

protected Object doInBackground() throws Exception {
Calendar calendario;
int thisHour;
int thisMin;
int thisSec;
System.out.println("iniciado!");
do{
calendario = Calendar.getInstance();
thisHour = calendario.get(Calendar.HOUR_OF_DAY);
thisMin = calendario.get(Calendar.MINUTE);
thisSec = calendario.get(Calendar.SECOND);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread sleep de ChekcHour a fallado");
}
}while(copyHour != thisHour || copyMin != thisMin || copySec != thisSec);
System.out.println("APAGATE!");
return null;
}

}


Sospecho que puede ser, que como yo genero un new time, cada vez que le de o a cancel o a programar, al darle a cancel me cancela el que genera cancel, pero no el anterior que genere con el program, pero bueno quiero escuchar segundas opiniones.

Un saludo y gracias de antemano.

Fakedo0r

#1
Hola, estoy en el trabajo y no puedo probar el código pero prueba así a ver si te funciona.

Código (java) [Seleccionar]
package base;

import java.util.Calendar;

import javax.swing.SwingWorker;

public class CheckTime extends SwingWorker{

private int copyHour;
private int copyMin;
private int copySec;
private boolean running;

public  CheckTime(int hour,int min, int sec){
copyHour = hour;
copyMin = min;
copySec = sec;
}

protected Object doInBackground() throws Exception {
Calendar calendario;
int thisHour;
int thisMin;
int thisSec;

System.out.println("iniciado!");
this.running = true;

do{
calendario = Calendar.getInstance();
thisHour = calendario.get(Calendar.HOUR_OF_DAY);
thisMin = calendario.get(Calendar.MINUTE);
thisSec = calendario.get(Calendar.SECOND);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread sleep de ChekcHour a fallado");
}
}while(copyHour != thisHour || copyMin != thisMin || copySec != thisSec || this.running);
System.out.println("APAGATE!");
return null;
}

public void stopThread() {
running = false;
}



Código (java) [Seleccionar]
public void actionPerformed(ActionEvent evt) {
CheckTime time = new CheckTime(hour.getSelectedIndex(), min.getSelectedIndex(), sec.getSelectedIndex());
if(evt.getSource() == programShutdown && isStarted == false){
System.out.println("iniciado!");
time.execute();
isStarted = true;
} else if(evt.getSource() == cancelShutdown && isStarted == true){
System.out.println("cancelado!");
time.stopThread();
isStarted = false;
}

}


Si algo, comenta.

Saludos.

Zoik

Bueno si no te importa e hecho unos cambios ya que si no nunca salia del bucle al llegar la hora, así cuando llega a la hora si que sale del bucle y "apaga el ordenador", pero e estado observando la variable running, y aún cambiandola desde el método, parece que el SwingWorker la sigue teniendo en true.

Código (java) [Seleccionar]
package base;

import java.util.Calendar;

import javax.swing.SwingWorker;

public class CheckTime extends SwingWorker{
private int copyHour;
private int copyMin;
private int copySec;
private boolean running;
public  CheckTime(int hour,int min, int sec){
copyHour = hour;
copyMin = min;
copySec = sec;
}

protected Object doInBackground() throws Exception {
Calendar calendario;
int thisHour;
int thisMin;
int thisSec;
System.out.println("iniciado!");
this.running = true;

do{
calendario = Calendar.getInstance();
thisHour = calendario.get(Calendar.HOUR_OF_DAY);
thisMin = calendario.get(Calendar.MINUTE);
thisSec = calendario.get(Calendar.SECOND);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread sleep de ChekcHour a fallado");
}
System.out.println(running);
if(this.running == false){
System.out.println("E cancelado el thread");
}
}while(copyHour != thisHour || copyMin != thisMin || copySec != thisSec);
System.out.println("APAGATE!");
return null;
}

public void stopThread() {
System.out.println("Estoy en stop y e puesto running a false");
running = false;
System.out.println("running = "+running);
}

}


Me explicaré mejor, enciendo el thread y en el bucle va printando true, el thread está encendido, le doy a cancelar, y en un println en el método de cancelar, veo como se cambia el valor de running, pero en el bucle que aún esta en marcha, continua printando true.

Un saludo y gracias.

Fakedo0r

#3
Hola, veo que no sabes trabajar con hilos. Ese código que has modificado esta mal ya que jamas saldrá del bucle aunque mandes la orden de terminar el hilo si no se cumple una de las 3 condiciones que has puesto. Por eso tenia la variable "running" como una condición más, para que en caso de que el valor del "running" fuera falsa, pues se rompiera el bucle. Prueba el que te puse y ponte a leer sobre los hilos si quieres aprender a manejar-los.

PD: Ahora que veo tenía un pequeño fallo en el código y por eso no funcionaba. Ya lo modifique.

Tenia puesto así:

Código (java) [Seleccionar]
public void stopThread() {
 running == false;
}


Pero es así:

Código (java) [Seleccionar]
public void stopThread() {
 running = false;
}


Ya que "==" es para comparar y no setear el valor.

Saludos.

Zoik

#4
Ciertamente nunca saldrá, pero ahora mismo acabo de copiar y pegar tu código, cuando llega la hora que e asigando en los jcombobox tendría que salir del bucle y printar apagate, y no me lo printa, es decir que no sale del bucle, y al darle a cacelar estoy en las mismas tampoco me sale.

En el que hice almenos me apagaba el ordenador, agradecería que me explicases un poco como funciona tu código, de mientras iré buscando mas documentación sobre threads.

Un saludo y gracias.

EDITO: Ese erro ya lo corregí, era obvio, pero yo sigo sin verlo...

Fakedo0r

Hola, amigo, me estoy bajando el eclipse desde mi despacho para probar y ver como que no funciona el código. Primero, no entiendo muy bien eso de componente jComboBox que dices ya que obviamente desde fuera no tienes acceso a tus atributos de la clase ya que son privadas. Segundo, tienes el objeto Calendar en un bucle y innecesariamente obtienes la instancia de la clase en cada vuelta, algo inútil. Y lo de explicar el código, ya te lo explique porque puse la variable "running". Normalmente cuando creas el hilo y quieres tenerlo en constante ejecución necesitas el uso de bucles. Cuando quieres terminar el hilo rompes el bucle y listo.

Zoik

Respecto a lo primero, porque no te e puesto todo el código  :silbar:.
Y lo segundo, bueno si te refieres a:

Código (java) [Seleccionar]
calendario = Calendar.getInstance();

Es debido a que a cada segundo quiero saber la hora, y la hora la extrae este comando, si lo pusiese fuera solo sabría la hora de el momento que le doy al botón, o eso entendi cuando lo estuve investigando.

si por otra parte te refieres a esto:

Código (java) [Seleccionar]
Calendar calendario;

Si, podría haberlo declarado arriba...

Agradezco el esfuerzo por un noob como yo  :)

Fakedo0r

#7
Hola, ya veo tu error, mi fallo técnico por no haber fijado en la condición que le das al bucle. Obviamente no saldrá del bucle en estado actual. Te pondre en pseudo-código para que entiendas.

Es tu condición:

Hacer {

var1
var2
var3

Las acciones

} (Mientras var1 sea diferente a X o mientras var2 sea diferente a x o mientras var3 sea diferente a X o mientras running sea true)


Es decir solo con que se cumpla una de las 4 condiciones seguirá dando vuelta sin tener en cuenta el valor de los otros, por lo tanto no saldrá del bucle. No se si me he explicado ?

Al final te quedaría:

Código (java) [Seleccionar]

package pkg_main;

import java.util.Calendar;

import javax.swing.SwingWorker;

public class CLS_CheckTime extends SwingWorker<Object, Object> {
private int copyHour;
private int copyMin;
private int copySec;
private boolean running;

public CLS_CheckTime(int hour, int min, int sec) {
copyHour = hour;
copyMin = min;
copySec = sec;
}

protected Object doInBackground() throws Exception {
Calendar calendario;

int thisHour;
int thisMin;
int thisSec;

this.running = true;

System.out.println("iniciado!");

do {
calendario = Calendar.getInstance();
thisHour = calendario.get(Calendar.HOUR_OF_DAY);
thisMin = calendario.get(Calendar.MINUTE);
thisSec = calendario.get(Calendar.SECOND);

System.out.println("funcionando: " + thisHour + ":" + thisMin + ":" + thisSec);

if (copyHour == thisHour && copyMin == thisMin && copySec == thisSec) {
this.running = false;
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread sleep de ChekcHour a fallado");
}
} while (this.running);

System.out.println("APAGATE!");
return null;
}

public void stopThread() {
this.running = false;
}
}


Espero que te haya servido. Saludos.

Zoik

Es decir que según tu razonamiento, si yo introduzco por ejemplo las 12:56:00 y el Calendar me coge 11:55:00, se me saldra del bucle ya que con que solo uno de los 3 digitos sea igual a el introducido se marchara, eso no es lo que quiero, quiero que salga del bucle, en dos casos, o que yo le de a cancelar, para eso esta el running, o que la hora que yo introduzca sea igual a la que me coja el Calendar.

Un saludo.

Fakedo0r

El código que te he dejado, evalúa los 3 valores y también el estado de running.

Si quieres por ejemplo solo evaluar la hora y el minuto, entonces quita la tercera condición y listo.
No hay nada complicado, lo que yo veo es que necesitas leer programación básica porque estas cosas son básicas y esenciales que deberías de saber antes de intentar trabajar con otras cosas más avanzadas.