Проблема заключается в том, что вы пытаетесь закрыть Stage
из потока другого , чем JavaFX Application Thread. Посмотрев документацию по Stage
, вы увидите:
Объекты сцены должны быть сконструированы и изменены в приложении JavaFX Application Thread.
Тема приложения JavaFX создается как часть процесса запуска для среды исполнения JavaFX. Дополнительную информацию см. В классе Application и методе Platform.startup (Runnable).
Тем не менее,
Service
при запуске выполнит свойTask
на фоне . В частности, методcall()
дляTask
выполняется на указанном фоновом потоке. Я только что протестировал попытку закрытьStage
в фоновом потоке, чтобы узнать, что произойдет (независимо от того, будет ли выбрано исключение). Результатом былjava.lang.IllegalStateException: Not on FX application thread; currentThread = Thread-3
.Причина, по которой вы этого не видите, - это не наблюдение за
Service
за сбой. Вы можете посмотреть ответ на этот вопрос , чтобы посмотреть, как смотреть на провал. Ответ конкретно говорит оTask
, но такое же поведение присутствует вService
.Что вам нужно сделать, чтобы заставить ваш код работать, чтобы убедиться, что
close()
вызывается в приложении JavaFX Нить. Самый простой способ сделать это - обернутьclose()
в вызовPlatform.runLater(Runnable)
.Service
cicle = new Service () { @Override protected Task createTask() { return new Task () { volatile boolean waiting = false; @Override protected Void call() throws Exception { Timer.start(); while (Timer.update() / 1000 < time) { System.out.println(Timer.update()) } Platform.runLater(() -> close()); // wrapped in Platform#runLater return null; } }; } }; Вы также можете отменить
Service.succeeded()
, который всегда будет вызываться в потоке приложений JavaFX (но только в случае успехаService
). В этом случае вы удалите вызовclose()
из методаcall()
.Service
cicle = new Service () { @Override protected Task createTask() { return new Task () { volatile boolean waiting = false; @Override protected Void call() throws Exception { Timer.start(); while (Timer.update() / 1000 < time) { System.out.println(Timer.update()) } return null; } }; } @Override protected void succeeded() { close(); } }; Существуют и другие способы: прослушивание свойства
state
с помощьюsetOnSucceeded(EventHandler)
, и т.д ...