我的问题是基于理论的问题,但它确实满足我的具体需求。在SwingWorker中处理错误
当你的SwingWorker抛出一个异常,你可以做什么,你可以预期和b)需要恢复和继续,但你想通知用户这个错误发生了?如何获取预期的例外情况并通知用户,而不违反“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<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();
}
}
}
是否有效调用doInBackground()
方法中SwingUtilities.invokeAndWait()
?我做了这方面的一些主题分析,结果是这样的:
一旦“转到”按钮被按下时,SwingWorker-pool-1-thread-1
线程变为绿色。那么,当if条件满足时,就会抛出错误,并显示错误对话框,线程将变为黄色,并且AWT-EventQueue-0
线程上确实有一个绿色的“blip”,表示EDT已被调用。我等了大约10秒,按下“确定”,并且SwingWorker
线程再次变绿。
这样做有什么潜在的缺陷吗?有没有人有从SwingWorker
实时通知用户计算错误的经验?
我会说实话,这种方法让我很沮丧。它似乎非正统,但我不能肯定地说这是否是一个坏主意。
如果是处理异常,你可以不用在'doInBackground'中返回'Void'而是用'errorCode'' description'返回一些bean,或者当异常发生时调用'publish'来获得'process'调用并处理异常,或者你可以使用发生错误的'firePropertyChange' – nachokk
确定我可以返回除'Void'之外的东西,但是它是我的SSCCE返回'Void'。我的真实应用可能需要返回中期结果。 – ryvantage
SwingWorker没有被正确地使用doInBackground(工作者线程,而不是invokeAndWait的地方,只有在Initial Tread之后不是EDT时,如果EDT处于活动状态,则会导致异常),使用JOptionPane的发布(在EDT上完成), – mKorbel