2017-05-24 4 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

이것은 유용하며 해결 방법을 표시하고 있지만 한 가지 문제가 있습니다. 무거운 작업은 JAR 파일 기능에 의해 수행되는 경우가 있습니다.이 작업은 단순히 호출되어 작동하기 위해 남겨졌습니다. 해당 코드는 표시되거나 편집 할 수 없으므로 답변에서 설명한대로 작업 취소를 확인할 수 없습니다. 이 사건을 둘러싼 다른 방법이 있습니까? –

관련 문제