簡體   English   中英

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

搜索網絡后,我發現以下來自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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM