问题
In a JavaFX application, I have a method which takes a long time on large input. I'm opening a dialog when it is loading and I'd like the user to be able to cancel/close out the dialog and the task will quit. I created a task and added its cancellation in the cancel button handling. But the cancellation doesn't happen, the task doesn't stop executing.
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws Exception {
// calling a function that does heavy calculations in another class
};
task.setOnSucceeded(e -> {
startButton.setDisable(false);
});
}
new Thread(task).start();
cancelButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent e) {
System.out.println("Button handled");
task.cancel();
}
);
Why isn't the task getting canceled when the button clicked?
回答1:
You have to check on the cancel state (see Task's Javadoc). Have a look at this MCVE:
public class Example extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
new AnotherClass().doHeavyCalculations(this);
return null;
}
};
Button start = new Button("Start");
start.setOnMouseClicked(event -> new Thread(task).start());
Button cancel = new Button("Cancel");
cancel.setOnMouseClicked(event -> task.cancel());
primaryStage.setScene(new Scene(new HBox(start, cancel)));
primaryStage.show();
}
private class AnotherClass {
public void doHeavyCalculations(Task<Void> task) {
while (true) {
if (task.isCancelled()) {
System.out.println("Canceling...");
break;
} else {
System.out.println("Working...");
}
}
}
}
}
Note that…
- You should use Task#updateMessage(String) rather than printing to
System.out
, here it's just for demonstration. - Directly injecting the
Task
object creates a cyclic dependency. However, you can use a proxy or something else that fits your situation.
来源:https://stackoverflow.com/questions/44153976/javafx-cancel-task-doesnt-work