运行此代码时,任务完成后会显示阶段。为什么会发生? 如何使阶段出现在任务之前?
private List<SensorEntity> detectSensors() throws URISyntaxException {
Task<List<SensorEntity>> task = new TryDetectTask(sensorForDiscover, wifiController);
ProgressIndicator indicator = new ProgressIndicator();
indicator.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
indicator.progressProperty().bind(task.progressProperty());
Stage stage = new Stage();
stage.setHeight(100);
stage.setWidth(200);
stage.initModality(WINDOW_MODAL);
stage.setScene(new Scene(indicator));
stage.show();
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<List<SensorEntity>> futureTask = executor.submit(task, null);
try {
return futureTask.get(30, SECONDS);
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
log.error(e);
e.printStackTrace();
}
executor.shutdown();
return null;
}
pane.getScene()。setRoot(),alert.show(),Platform.runLater和其他结果相同,但是showAndWait()可以正常工作。
答案 0 :(得分:1)
futureTask.get(30, SECONDS)
将一直阻塞,直到结果可用或经过30秒为止。由于您是在JavaFX应用程序线程上执行此操作,因此在此期间,GUI的所有更新都被阻止。
showAndWait
“有效”,因为此调用可确保GUI仍在更新,但是此方法仅在阶段关闭时返回,这意味着您稍后只需冻结GUI。
最好将Consumer<List<SensorEntity>>
传递给使用任务结果执行代码的方法。
private void detectSensors(Consumer<List<SensorEntity>> consumer) throws URISyntaxException {
final boolean[] boolRef = new boolean[1];
Task<List<SensorEntity>> task = new TryDetectTask(sensorForDiscover, wifiController);
task.setOnSucceeded(evt -> {
if (!boolRef[0]) {
boolRef[0] = true;
// submit result unless timeout happened
consumer.accept(task.getValue());
}
});
ProgressIndicator indicator = new ProgressIndicator();
indicator.setProgress(ProgressIndicator.INDETERMINATE_PROGRESS);
indicator.progressProperty().bind(task.progressProperty());
Stage stage = new Stage();
stage.setHeight(100);
stage.setWidth(200);
stage.initModality(WINDOW_MODAL);
stage.setScene(new Scene(indicator));
stage.show();
// a thread does not need to be shut down
Thread thread = new Thread(task);
thread.setDaemon(true);
PauseTransition pause = new PauseTransition(Duration.seconds(30));
pause.setOnFinished(evt -> {
if (!boolRef[0]) {
boolRef[0] = true;
// submit null unless task has finished successfully
consumer.accept(null);
}
});
thread.start();
pause.play();
}