使用 SwingWorker 时,我应该如何处理异常?

2022-09-01 21:19:34

我在Java 6中使用SwingWorker来避免在事件调度线程上运行长时间运行的代码。

如果在我的 done() 方法中对 get() 的调用返回异常,那么处理异常的适当方法是什么?

我特别担心可能的中断异常。JavaDoc示例只是忽略了异常,但多年来我了解到,吞下异常会导致代码难以调试。

示例用法如下:

new SwingWorker<String, Void>() {

    @Override
    protected String doInBackground() throws Exception {
        // do long-running calculation
        return result;
    }

    @Override
    protected void done() {
        try {
            setTextField(get());
        } catch (InterruptedException e) {
            e.printStackTrace();  
        } catch (ExecutionException e) {
            e.printStackTrace();  
        }
    }
}.execute();

答案 1

这是一篇旧帖子,但我想做一些澄清:

SwingWorker.get 将 InterruptedException,ExecutionException 作为已检查的异常。

另外,它会引发一个非常具体的未经检查的异常,即 CancelException。当然,它可能会引发任何未经检查的异常,但UnucationException并不是一个“例外”和意外的异常。当您尝试在调用 cancel 后调用 get 方法时,将引发该消息。

ExecutedException 在 doInBackground 中引发异常时被抛出。原始异常被包装在执行异常中。当调用 get() 方法时,将抛出 ExecutionException。拿出原始异常并进行管理的想法很好。(正如埃米尔·H指出的那样)。

取消例外是未选中的,在我看来应该检查。API实现不检查它的唯一借口是它有一个状态方法是Cancelled()。
你可以:
- 测试isCancelled()如果是真的,不要调用get(),因为它会抛出UnjectException
- 用尝试捕获包围get()并添加Un cancelException,因为unchecked不会被编译器
请求 - 取消例外的事实让你自由地忘记所有这些东西,并获得一个很好的惊喜。
- 做任何事情,因为你不会取消工人

中断异常。如果您取消带有 cancel(true) 的 SwingThread,doInBackground 中的第一个可中断方法调用(对于 Sure Thread.sleep、this.wait,也许是一些 IO 方法)将抛出 InterruptException。但是,此异常未包装在 ExecuteException 中。doInBackground 将终止,并出现中断异常。如果它被捕获并转换为其他异常,这些将被忽略,因为此时取消已经在EDT上调用了SwingThread.done,如果完成调用了get,则它只获得了标准的Un cancelException。不是中断的异常!

如果使用 cancel(false) 取消,则不会在 doInBackground 中引发中断异常。如果使用 cancel(true) 取消也是如此,但 doInBackground 中没有可中断的方法调用。在这些情况下,doInBackground 将遵循其自然循环。此循环应测试 isCancelled 方法并正常退出。如果 doInBackground 不这样做,它将永远运行。我没有测试超时的存在,但我不相信。

对我来说,它仍然只是一个灰色地带。在哪些情况下被get抛出中断异常?我希望看到一些简短的代码,因为我无法产生类似的异常。:-)

附言:我在另一个问答中记录了在取消的情况下,在doInBackground退出之前调用已完成和状态更改侦听器。由于这是事实,因此在设计doInBackground方法时需要特别注意这一点 - 这不是一个错误。如果您对此感兴趣,请参阅 SwingWorker:究竟何时被称为 done 方法?


答案 2

这在很大程度上取决于后台作业可能导致的错误类型。如果 doInBackground 中的作业引发异常,它将作为嵌套的执行异常传播到 done 方法。在这种情况下,最佳做法是处理嵌套异常,而不是执行异常本身。

例如:如果工作线程引发异常,指示数据库连接已丢失,则可能需要重新连接并重新启动作业。如果要完成的工作依赖于某种资源,而该资源实际上已在使用中,则最好为使用提供重试或取消选项。如果引发的异常对用户没有任何影响,只需记录错误并继续。

根据我的记忆,我相信中断的异常在这里不会是一个问题,因为你在完成的方法中进行了get方法调用,因为只有在等待后台作业完成时get调用中断时,才会引发中断的Exception。如果发生此类意外事件,您可能希望显示错误消息并退出应用程序。


推荐