SwingWorker中的error handling

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

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

考虑到这个问题,我已经开发了一个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 { 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(); } } } 

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

在此处输入图像描述

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

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

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

我发现当用户实际需要批准时使用invokeAndWait()没有问题。 如果没有,如本例所示, SwingWorker可以简单地调用publish()其中数据和错误消息是交错的。 在done()附加的合适消息将允许用户在必要时查看累积的输出。