SwingWorker中的错误处理

ryv*_*age 5 java swing swingworker event-dispatch-thread invokeandwait

我的问题是基于理论的问题,但它确实满足了我的特定需求.

当你的SwingWorker抛出a)你可以预料到并且b)需要从中恢复并继续的异常时,你会怎么做,但是你想通知用户这个错误已经发生了?如何获取预期的异常并通知用户而不违反"No Swing code from doInBackground()"规则?

考虑到这个问题,我已经开发了一个SSCCE,我想提出下面的问题.

SSCCE:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;

public class Test {

    public static void main(String args[]) {
        final JFrame frame = new JFrame();
        JButton go = new JButton("Go.");
        go.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                new Task(frame);
            }
        });
        frame.add(go);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    static class Task extends SwingWorker<Void, Void> {
        JFrame parent;
        JDialog dialog;
        public Task(JFrame parent) {
            this.parent = parent;
            dialog = new JDialog(parent);
            JProgressBar jpb = new JProgressBar();
            jpb.setIndeterminate(true);
            dialog.add(jpb);
            dialog.setLocationRelativeTo(null);
            dialog.setVisible(true);
            execute();
        }

        @Override
        protected Void doInBackground() throws Exception {
            for(int i = 0; i < 100000; i++) {
                System.out.println(i);
                try {
                    if(i == 68456) throw new IllegalStateException("Yikes! i = 68456.");
                } catch (final IllegalStateException e) {
                    SwingUtilities.invokeAndWait(new Runnable() {
                        @Override
                        public void run() {
                            JOptionPane.showMessageDialog(parent, "Error: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                        }
                    });
                }
            }
            return null;
        }

        @Override
        protected void done() {
            if (!isCancelled()) {
                try {
                    get();
                } catch (ExecutionException | InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("done");
            dialog.dispose();
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

SwingUtilities.invokeAndWait()doInBackground()方法中调用是否有效?我对此进行了一些线程分析,结果如下:

在此输入图像描述

按下"开始"按钮后,SwingWorker-pool-1-thread-1线程变为绿色.然后,当满足if条件时,抛出错误,并显示错误对话框,线程变黄,并且线程上确实存在绿色"blip" AWT-EventQueue-0,表示已调用EDT.我等了大约10秒钟,按下"确定",然后SwingWorker线程又变绿了.

做这样的事情有没有潜在的陷阱?有没有人有从实时通知用户计算错误的经验SwingWorker

老实说,这种做法让我很伤心.这似乎是非正统的,但我无法确定这是否是一个坏主意.

tra*_*god 4

invokeAndWait()当用户实际需要批准时,我认为使用没有问题。如果没有,如本示例所示,aSwingWorker<Void, String>可以简单地调用publish()交错的数据和错误消息。如有必要,附加的适当消息done()将允许用户查看累积的输出。