JavaFX的任务似乎消耗了exception。 它是一个bug还是一个function?

考虑以下代码:

Thread.setDefaultUncaughtExceptionHandler((Thread t, Throwable e) -> { System.out.println("An exception occurred!"); }); // set the exception handler for the JavaFX application thread Thread.currentThread().setUncaughtExceptionHandler((Thread t, Throwable e) -> { System.out.println("An exception occurred!"); }); Task task = new Task() { @Override public Void call() throws Exception { throw new RuntimeException("foobar"); }; }; new Thread(task).start(); 

如果我们运行代码,运行时exception永远不会触发默认的exception处理程序,而是由任务使用。 我发现的抵消这种情况的唯一方法是在task.setOnFailed中重新抛出exception:

 task.setOnFailed((WorkerStateEvent t) -> { throw new RuntimeException(task.getException()); }); 

既然JavaFX 8现在支持UncaughtExceptionHandler,为什么不将exception传播到exception处理程序?

function,任务维护exception属性本身。 这个想法是,当抛出exception时,任务失败,并且可能会询问抛出了哪个exception。 在这方面,任务被认为是一个准批处理作业,在后台运行,并可能默默地失败。

这也反映了一些异步行为; 可以处理exception的地方不是在叫做start的地方。

Task.call()方法内部,只需抛出exception并将ChangeListener添加到任务中,如下所示:

 task.exceptionProperty().addListener((observable, oldValue, newValue) -> { if(newValue != null) { Exception ex = (Exception) newValue; ex.printStackTrace(); } }); 

然后,在任务因exception而失败之后,监听器会通知您在执行期间抛出了哪个exception。 您可以轻松地交换ex.printStackTrace(); 如果您在JavaFX执行线程中,则使用Alert

可能有点晚了,但你可以打印throwable本身:

 task.setOnFailed(new EventHandler() { @Override public void handle(WorkerStateEvent arg0) { Throwable throwable = task.getException(); throwable.printStackTrace(); } } 

无论如何都会抛出exception,但您可以使用它将其显示给用户或进行记录。

我知道这个问题已经过时了,但我找了一个答案,并没有找到很多关于这个话题。 如果您愿意,我想您可以重新抛出exception。 以下是示例代码:

 public class Main extends Application { @Override public void start(Stage stage) { Task task = new Task() { @Override protected Void call() throws Exception { throw new IndexOutOfBoundsException(); } }; task.setOnSucceeded(evt -> System.out.println("Task succeeded!")); task.setOnCancelled(evt -> System.out.println("Task cancelled!")); task.setOnFailed(evt -> { System.out.println("Task failed!"); if (task.getException() instanceof IndexOutOfBoundsException) { System.out.println("...with an IndexOutOfBoundsException"); } else if (task.getException() instanceof NumberFormatException) { System.out.println("...with a NumberFormatException"); } else { System.out.println("...with another, unexpected execption"); } }); VBox box = new VBox(); Scene scene = new Scene(box, 200, 200); stage.setScene(scene); stage.setTitle("Thread Example"); stage.show(); new Thread(task).start(); } public static void main(String[] args) { launch(args); } } 

控制台输出:任务失败! …带有IndexOutOfBoundsException

如果在任务中抛出exception,则任务最终处于“失败”状态。 在setOnFailed方法中,您可以处理任务的失败。 此方法中的所有代码都在JavaFX的应用程序线程上,但您可以通过task.getException()依赖任务的exception。 此外,此代码仅适用于JavaFX(我试图在普通的Java应用程序中获得相同的输出,但它没有用)。