考虑以下代码:
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();
如果我们运行代码,运行时异常永远不会触发默认的异常处理程序,而是由任务使用。解决这个问题的唯一方法就是在task.setOnFailed中重新抛出异常:
task.setOnFailed((WorkerStateEvent t) -> {
throw new RuntimeException(task.getException());
});
由于JavaFX 8现在支持UncaughtExceptionHandler,为什么不将异常传播到异常处理程序?
答案 0 :(得分:8)
在Task.call()
方法内部,只需抛出异常并向此任务添加ChangeListener
,如下所示:
task.exceptionProperty().addListener((observable, oldValue, newValue) -> {
if(newValue != null) {
Exception ex = (Exception) newValue;
ex.printStackTrace();
}
});
然后,在任务因异常而失败后,监听器会通知您在执行期间抛出了哪个异常。如果您在JavaFX执行线程中,则可以轻松地将行ex.printStackTrace();
与Alert
交换。
答案 1 :(得分:6)
可能有点迟,但你可以打印throwable本身:
task.setOnFailed(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent arg0) {
Throwable throwable = task.getException();
throwable.printStackTrace();
}
}
无论如何都会抛出异常,但您可以使用它向用户显示或记录它。
答案 2 :(得分:5)
功能,任务本身维护exception
属性。这个想法是,当抛出异常时,任务失败,并且可能会询问抛出了哪个异常。在这方面,Task被认为是一个准批处理作业,在后台运行,可能会默默地失败。
这也反映了异步行为的一点点; 其中可以处理异常。 不在start
被调用的地方。
答案 3 :(得分:2)
我知道这个问题很老,但是我搜索了一个答案,并没有找到很多关于这个主题的内容。如果您愿意,我认为您可以重新抛出异常。以下是示例代码:
public class Main extends Application {
@Override
public void start(Stage stage) {
Task<Void> task = new Task<Void>() {
@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
如果在任务中抛出异常,则任务最终处于“失败”状态。在setOnFailed方法中,您可以处理任务的失败。此方法中的所有代码都在JavaFX的应用程序线程上,但您可以通过task.getException()依赖任务的异常。此外,此代码仅适用于JavaFX(我试图在普通的Java应用程序中获得相同的输出,但它没有用完)。