[英]SwingWorker: error thrown when done() is called after worker thread is cancelled
取消SwingWorke
任務后,我一直看到以下異常。
Exception in thread "AWT-EventQueue-0" java.util.concurrent.CancellationException
搜索網絡后,我發現以下來自Oracle的評論
注意:如果取消了SwingWorker對象的后台任務后對其進行調用,則會引發java.util.concurrent.CancellationException。
這是我的生成異常的代碼。
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();
});
}
}
我尋找一個解決方案,我看到了這個和這個,但我無法fit
我的情況。
這就是我在done()
方法中為解決問題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並對其進行處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.