Multithreading JavaFX-取消任务不';行不通

Multithreading JavaFX-取消任务不';行不通,multithreading,javafx,task,cancel-button,Multithreading,Javafx,Task,Cancel Button,在JavaFX应用程序中,我有一个方法,它需要花费很长时间处理大量输入。我正在加载一个对话框,我希望用户能够取消/关闭该对话框,任务将退出。我创建了一个任务并将其取消添加到cancel按钮处理中。但是取消不会发生,任务不会停止执行 Task<Void> task = new Task<Void>() { @Override public Void call() throws Exception { // calling a function

在JavaFX应用程序中,我有一个方法,它需要花费很长时间处理大量输入。我正在加载一个对话框,我希望用户能够取消/关闭该对话框,任务将退出。我创建了一个任务并将其取消添加到cancel按钮处理中。但是取消不会发生,任务不会停止执行

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();
}
);
Task Task=新任务(){
@凌驾
public Void call()引发异常{
//调用在另一个类中执行大量计算的函数
};
task.setonsucceed(e->{
startButton.setDisable(假);
});
}
新线程(任务).start();
cancelButton.setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent e){
System.out.println(“按钮处理”);
task.cancel();
}
);

为什么单击按钮时任务没有被取消?

您必须检查取消状态(请参阅)。请查看以下内容:

公共类示例扩展了应用程序{
@凌驾
public void start(Stage primaryStage)引发异常{
任务=新任务(){
@凌驾
受保护的Void调用()引发异常{
新的另一个类().doHeavyCalculations(此);
返回null;
}
};
按钮启动=新按钮(“启动”);
setOnMouseClicked(事件->新线程(任务).start());
按钮取消=新按钮(“取消”);
取消.setOnMouseClicked(事件->任务.cancel());
设置场景(新场景(新HBox(开始,取消));
primaryStage.show();
}
私有类另一类{
公共无效doHeavyCalculations(任务){
while(true){
if(task.isCancelled()){
System.out.println(“取消…”);
打破
}否则{
System.out.println(“工作…”);
}
}
}
}
}
请注意

  • 您应该使用而不是打印到
    System.out
    ,这里只是为了演示
  • 直接注入
    任务
    对象会创建循环依赖关系。但是,您可以使用代理或其他适合您的情况的方法

您必须在实现中处理取消任务的问题。请阅读中示例前的最后一段:“任务的用户将请求取消任务,任务的作者必须在调用方法的主体中检查is是否已被取消。”@sillyfly是的,这很有用。但是如果任务的重要部分是在另一个类的函数中完成的,我如何检查任务的取消?这在很大程度上取决于另一个类的实现。没有“包罗万象”的解决方案,但通常您的任务由许多较小的“步骤”组成,因此您可以在每次迭代中检查一个标志,或者使用某种形式的
等待
,它将响应
中断
。这是非常有用的(尽管很旧)解释线程中断,并可能提供执行所需操作的方法。@sillyfly我的实现实际上是一个JAR文件方法,我调用它并从中获取结果。在这种情况下,有什么方法可以取消任务吗?如果繁重的任务是由另一个类中的函数完成的呢?如果为true,不意味着永远不会执行吗r end?@Joker00使该类了解取消状态。例如,将
任务
对象作为方法参数注入。请参见编辑…这很有用,我将您的答案标记为解决问题,但我仍然有一个问题,繁重的任务有时由JAR文件函数完成,这只是调用并让其工作。其代码不可见e也不可编辑,因此,我无法按照您在回答中解释的方式检查任务的取消。是否有其他方法解决此问题?@Joker00很高兴这确实有帮助。关于您的后续问题:您可能想看看
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...");
                }
            }
        }

    }

}