2017-05-24 8 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を見ている:あなたは、むしろSystem.outに印刷するよりもTask#updateMessage(String)を使用する必要があります...

  • 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オブジェクトを直接注入すると、循環依存性が作成されます。しかし、あなたの状況に合ったプロキシなどを使用することができます。
+0

重い作業が別のクラスの関数によって行われたらどうなりますか? 真実は実行が決して終わらないという意味ですか? –

+1

@ Joker00はそのクラスをキャンセル状態に気づかせます。例えば、 'Task'オブジェクトをメソッドのパラメータとして注入します。編集を参照してください... – beatngu13

+0

これは便利ですし、私はあなたの答えをマークしていますが、まだ1つの問題があります。重い作業は時々JARファイル関数によって行われます。そのコードは表示も編集もできないため、解答で説明したようにタスクのキャンセルを確認することはできません。この場合、他の方法はありますか? –

関連する問題