SwingWorker:取消工作线程后调用 done() 时抛出错误
SwingWorker: error thrown when done() is called after worker thread is cancelled
我在取消 SwingWorke
任务后看到以下异常。
Exception in thread "AWT-EventQueue-0" java.util.concurrent.CancellationException
网上搜索后发现below comment from Oracle
Note: If get is invoked on a SwingWorker object after its background
task has been cancelled, java.util.concurrent.CancellationException is
thrown.
这是我生成异常的代码。
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
public class JasperReportGenerator {
private JButton cancel;
private JProgressBar pbar;
private int count = 0;
private JFrame dialog;
public JasperReportGenerator() {
init();
//Here we do the background task
SwingWorker<Boolean, Integer> worker = new SwingWorker<Boolean, Integer>() {
@Override
protected Boolean doInBackground() throws Exception {
for (int i = 0; i < 10; i++) {
publish(i * 10);
Thread.sleep(1000);
}
return true;
}
@Override
protected void done() {
try {
dialog.dispose();
JOptionPane.showMessageDialog(null, "Done", get().toString(), JOptionPane.INFORMATION_MESSAGE);
} catch (InterruptedException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
protected void process(List<Integer> list) {
pbar.setValue(list.get(list.size() - 1));
pbar.setString(list.get(list.size() - 1) + "%");
}
};
worker.execute();
//cancel the process
cancel.addActionListener((ActionEvent e) -> {
worker.cancel(true);
dialog.dispose();
System.out.println("bg task cancelled...");
});
}
private void init() {
dialog = new JFrame("Progress Report");
dialog.setLocationRelativeTo(null);
cancel = new JButton("Cancel");
pbar = new JProgressBar(0, 100);
pbar.setStringPainted(true);
pbar.setIndeterminate(false);
dialog.setPreferredSize(new Dimension(400, 250));
dialog.setLayout(new FlowLayout());
dialog.getContentPane().add(pbar);
dialog.getContentPane().add(cancel);
dialog.pack();
dialog.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(() -> {
new JasperReportGenerator();
});
}
}
我搜索了一个解决方案,我看到了 this and this 但我无法 fit
我的情况。
这是我done()
解决问题的方法
@Override
protected void done() {
try {
if (!isCancelled()) {
JOptionPane.showMessageDialog(null, "Done", get().toString(), JOptionPane.INFORMATION_MESSAGE);
dialog.dispose();
}
} catch (InterruptedException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
我的done()
如上设计,异常没有抛出
现在我想知道这是否是nice
解决方案?此代码的含义是什么?
您的解决方案不完善,因为取消可能发生在您调用 isCancelled() 和调用 get() 之间,这很少会导致异常。更好的方法是捕获 CancellationException 并处理它。
我在取消 SwingWorke
任务后看到以下异常。
Exception in thread "AWT-EventQueue-0" java.util.concurrent.CancellationException
网上搜索后发现below comment from Oracle
Note: If get is invoked on a SwingWorker object after its background task has been cancelled, java.util.concurrent.CancellationException is thrown.
这是我生成异常的代码。
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
public class JasperReportGenerator {
private JButton cancel;
private JProgressBar pbar;
private int count = 0;
private JFrame dialog;
public JasperReportGenerator() {
init();
//Here we do the background task
SwingWorker<Boolean, Integer> worker = new SwingWorker<Boolean, Integer>() {
@Override
protected Boolean doInBackground() throws Exception {
for (int i = 0; i < 10; i++) {
publish(i * 10);
Thread.sleep(1000);
}
return true;
}
@Override
protected void done() {
try {
dialog.dispose();
JOptionPane.showMessageDialog(null, "Done", get().toString(), JOptionPane.INFORMATION_MESSAGE);
} catch (InterruptedException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
@Override
protected void process(List<Integer> list) {
pbar.setValue(list.get(list.size() - 1));
pbar.setString(list.get(list.size() - 1) + "%");
}
};
worker.execute();
//cancel the process
cancel.addActionListener((ActionEvent e) -> {
worker.cancel(true);
dialog.dispose();
System.out.println("bg task cancelled...");
});
}
private void init() {
dialog = new JFrame("Progress Report");
dialog.setLocationRelativeTo(null);
cancel = new JButton("Cancel");
pbar = new JProgressBar(0, 100);
pbar.setStringPainted(true);
pbar.setIndeterminate(false);
dialog.setPreferredSize(new Dimension(400, 250));
dialog.setLayout(new FlowLayout());
dialog.getContentPane().add(pbar);
dialog.getContentPane().add(cancel);
dialog.pack();
dialog.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(() -> {
new JasperReportGenerator();
});
}
}
我搜索了一个解决方案,我看到了 this and this 但我无法 fit
我的情况。
这是我done()
解决问题的方法
@Override
protected void done() {
try {
if (!isCancelled()) {
JOptionPane.showMessageDialog(null, "Done", get().toString(), JOptionPane.INFORMATION_MESSAGE);
dialog.dispose();
}
} catch (InterruptedException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(JasperReportGenerator.class.getName()).log(Level.SEVERE, null, ex);
}
}
我的done()
如上设计,异常没有抛出
现在我想知道这是否是nice
解决方案?此代码的含义是什么?
您的解决方案不完善,因为取消可能发生在您调用 isCancelled() 和调用 get() 之间,这很少会导致异常。更好的方法是捕获 CancellationException 并处理它。