SwingWorker 的 done() 方法在处理 JDialog

问题描述

我有一个 SwingWorker 类,它的 doInBackground 在远程数据库上执行查询。我调用 publish(true)setVisible 设置为 true 以使 jdialog 保持加载器动画。

一切正常:

  1. 后台方法启动。
  2. 显示jdialog 模式。
  3. 后台方法完成。
  4. jdialog 在 done() 方法中隐藏/处理。
  5. 用户界面已更新为数据库值。

但是,当我将应用程序指向在本地计算机上运行的数据库时,会显示 jdialog,但从未关闭/处置,即使调用done()。这也会停止执行 done 方法中的 UI 代码,直到我手动关闭加载器对话框。

这种奇怪的行为如下:

  1. 后台方法启动。
  2. 显示jdialog 模式。
  3. 后台方法完成。
  4. jdialog 隐藏/处理在 done() 方法中。
  5. 用户界面更新

我必须提到,在远程数据库上执行需要 10 秒或更长时间,但在我的本地数据库上只需要一秒钟。更快的速度如何导致这种奇怪的行为?

以下是我的代码片段:

@H_502_54@ new SwingWorker<Void,Boolean>() { jdialog loader = new MyDialogLoader(); @Override protected Void doInBackground() { publish(true); //DATABASE EXECUTION CODE IS HERE publish(false); return null; } @Override protected void process(List<Boolean> chunks) { for (Boolean val : chunks) { loader.setVisible(val); } } @Override protected void done() { loader.dispose(); //UI UPDATE WITH DATABASE VALUES CODE HERE; } }.execute();

解决方法

可能是在 doBackground() 中抛出了一个异常,所以 publish(false) 没有被执行。可能是访问数据库出错...

doBackground 抛出的异常被 SwingWorker 静默捕获并保存。检查是否抛出此类异常的方法是调用 get() 方法中的 done() 方法。它将抛出一个 ExecutionException,原始异常为 cause:

    @Override
    protected void done() {
        loader.dispose();
        try {
            get();
        } catch (ExecutionException ex) {
            ex.printStackTrace();
            // some message or what ever using ex.getCause()
        } catch (InterruptedException ex) {
            ex.printStackTrace();
            // TODO
        }

        //UI UPDATE WITH DATABASE VALUES CODE HERE;
    }
,

我分享这个作为答案,因为它已经解决了这个问题。

我取消了 publishprocess 方法;加载器 JDialog 现在从 doInBackground 可见。为确保在事件调度线程上执行此 UI 交互,该语句放置在 SwingUtilities.invokeLater 中。

new SwingWorker<Void,Void>() {
        JDialog loader = new MyDialogLoader();
        @Override
        protected Void doInBackground() {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            try {
                                loader.setVisible(true);
                            } catch (Exception e) {
                                e.printStackTrace()
                            }
                        }
                    });
    
            //DATABASE EXECUTION CODE IS HERE

            return null;
        }

        @Override
        protected void done() {
            loader.dispose();
            //UI UPDATE WITH DATABASE VALUES CODE HERE;
        }
    }.execute();