multithreadingjavafxtaskcancel-button

JavaFX - Cancel Task doesn't work


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?


Solution

  • 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…