I\'m new with JavaFX and I\'ve a little problem with a thread: I can execute it twice and I can\'t find why.
Here is a sum-upt of my code:
Task
With a button can fire new tasks
Button btn = new Button();
btn.setText("New task");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Executor ex=new Executor("Task"+count);
ex.start();
count++;
System.out.println("Task Starting...");
}
});
Do it with a wraper class
import java.io.IOException;
import javafx.concurrent.Task;
public class Executor {
private String name;
private Task<Void> task;
public Executor(final String name) {
this.name=name;
task = new Task<Void>() {
@Override
public Void call() throws IOException, InterruptedException {
try {
int i=0;
while(i<20){
System.out.println(name);
Thread.sleep(2000);
i++;
}
return null;
} catch (IllegalThreadStateException e) {
System.out.println(e);
}
return null;
}
@Override
protected void succeeded() {
super.succeeded();
try {
System.out.println(name+" finish");
} catch (Exception ex) {
System.out.println(ex);
}
}
};
}
public void start() {
try {
Thread th = new Thread(task);
th.start();
} catch (Exception ex) {
System.out.println(ex);
}
}
}
From the Thread.start() documentation : No
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
From the Concurrency in JavaFX tutorial :
The Task class defines a one-time object that cannot be reused. If you need a reusable Worker object, use the Service class.
So, you have to consider the Service class rather than Task.
Edit: this should work for you:
Service service = new Service<>(task);
//Updated use this to create a new Service object instead
Service service = new Service() {
@Override
protected Task createTask() {
return new Task() {
@Override
protected Void call() throws Exception {
//Your codes here
return null;
}
};
}
};
@FXML protected void launch(ActionEvent event){
if (!service.isRunning()) {
service.reset();
service.start();
}
}