JavaFX的任务似乎消耗了异常.这是一个错误还是一个功能?

use*_*555 21 java javafx-8

考虑以下代码:

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();
Run Code Online (Sandbox Code Playgroud)

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

task.setOnFailed((WorkerStateEvent t) -> {
    throw new RuntimeException(task.getException());
});
Run Code Online (Sandbox Code Playgroud)

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

小智 9

Task.call()方法内部只是抛出异常并添加ChangeListener到这样的任务:

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

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


Joo*_*gen 8

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

这反映了一点异步行为; 可以处理异常的地方.不是在start被叫的地方.

  • 你不能。如您在文档(https://docs.oracle.com/javafx/2/api/javafx/event/EventHandler.html)中所见,Eventhandler的handle-method不会引发任何异常。您也不能将Exception给予周围的块以重新抛出,因为该块已经由于异步调用而被删除。 (2认同)

Pet*_*ter 6

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

task.setOnFailed(new EventHandler<WorkerStateEvent>() {
    @Override
    public void handle(WorkerStateEvent arg0) {
        Throwable throwable = task.getException(); 
        throwable.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

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