2017-05-24 90 views
2

在JavaFX應用程序中,我有一種方法需要很長時間處理大量輸入。我在加載時打開一個對話框,我希望用戶能夠取消/關閉對話框,任務將退出。我創建了一個任務並在取消按鈕處理中添加了它的取消。但是取消不會發生,任務不會停止執行。JavaFX - 取消任務不起作用

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(); 
} 
); 

爲什麼當按鈕被點擊時不會取消任務?

+2

您必須處理取消執行中的任務。請閱讀[文檔](https://docs.oracle.com/javase/8/javafx/api/javafx/concurrent/Task.html)中示例前面的最後一段:「任務的用戶將要求它將被取消,並且任務的作者必須檢查是否在呼叫方法的主體內被取消。「 – Itai

+0

@sillyfly是的,這很有用。但是,如果重大部分是在另一個類的函數中完成的,我該如何檢查任務的取消? –

+1

這在很大程度上取決於其他類的實現。沒有「全面解決方案」的解決方案,但通常你或者有一個任務由很多較小的「步驟」組成,所以你可以在每次迭代中檢查一個標誌,或者你有某種形式的「等待」,它會響應到一個「中斷」。 – Itai

回答

3

您必須檢查取消狀態(請參閱Task's Javadoc)。看看這個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..."); 
       } 
      } 
     } 

    } 

} 

注意...

  • 你應該使用Task#updateMessage(String),而不是打印到System.out,這裏只是爲了演示。
  • 直接注入Task對象會創建循環依賴關係。但是,您可以使用代理或適合您情況的其他內容。
+0

如果重任務是由另一個類中的某個函數完成的,該怎麼辦? 而不是真的意味着執行永遠不會結束? –

+1

@ Joker00讓這個班級知道取消狀態。例如,注入'Task'對象作爲方法參數。請參閱編輯... – beatngu13

+0

這很有用,我將您的答案標記爲解決問題,但我仍然遇到一個問題,繁重的任務有時由JAR文件函數完成,只需調用它即可繼續工作。它的代碼不可見也不可編輯,因此,我無法按照您在答案中解釋的方式檢查任務的取消。有沒有其他解決方案? –