如何在 javafx 中操作 Future 的结果

How to manipulate the result of a Future in javafx

这是我的 JavaFX 控制器

public class MainController {
   private Future<Graph> operation;
   private ExecutorService executor = Executors.newSingleThreadExecutor();

   @FXML
   private void createSession() { //invoked by a button click in the view
      //GraphCreationSession implements Callable<Graph>
      GraphCreationSession graphSession = new GraphCreationSession();

      if (operation != null && !operation.isDone()) {
         //cancel previous session
         operation.cancel(true);
      }
      operation = executor.submit(graphSession);
      ???
    }
 }

所以我的问题是,在 javaFX 上下文中处理 Future 结果的成语是什么?

我知道我可以 operation.get() 线程将阻塞直到操作完成,但我会阻塞应用程序线程。我正在考虑 Callable 完成时的回调,我发现 CompletableFuture,哪种方式通过 thenAccept but based on this answer 线程仍将被阻塞,这失败了未来的重点,就像答案提到的那样。

在我的特定情况下,Callable(示例中的图表)的结果包含一个我希望在操作完成时显示在面板中的结果。

最简单的方法是更改​​ GraphCreationSession,使其成为 Task<Graph> 的子类,而不是 Callable<Graph> 的实现:

public class GraphCreationSession extends Task<Graph> {

    @Override
    public Graph call() throws Exception {
        // implementation as before...
    }
}

那你可以做

public class MainController {
   private ExecutorService executor = Executors.newSingleThreadExecutor();
   private GraphCreationSession graphSession ;

   @FXML
   private void createSession() { //invoked by a button click in the view

      if (graphSession != null && !graphSession.getState()==Worker.State.RUNNING) {
         //cancel previous session
         graphSession.cancel(true);
      }
      graphSession = new GraphCreationSession();
      graphSession.setOnSucceeded(event -> {
          Graph graph = graphSession.getValue();
          // update UI...
      });
      executor.execute(graphSession);
    }
 }

如果您不能更改 GraphCreationSession,或者希望它独立于 javafx API,那么只需将其包装在一个简单的 Task 实现中:

public class MainController {

    private Task<Graph> graphSession ;
    // ...

    @FXML
    public void createSession() {

        // ...

        graphSession = new Task<Graph>() {
            @Override
            public Graph call() throws Exception {
                return new GraphCreationSession().call();
            }
        };

        graphSession.setOnSucceeded(...);
        executor.execute(graphSession);
   }
}