0

I have been seeing the following exception after cancelling SwingWorke task.

Exception in thread "AWT-EventQueue-0" java.util.concurrent.CancellationException

After searching the net I found 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.

This is my code that generates the exception.

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();
        });
    }

}

I search of a solution I saw this and this but I could not fit them in my case.

This is what I have done in my done() method to solve the problem

  @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);
            }
        }

With my done() designed as above, the exception is not throw.

Now I would like to know if this is a nice solution? What are the implications of this code?

CN1002
  • 1,115
  • 3
  • 20
  • 40

1 Answers1

1

Your solution is imperfect since cancellation could occur between the time you call isCancelled() and the time you call get() which would, rarely, still result in the exception. Better would be to catch the CancellationException and handle it.

Warren Dew
  • 8,790
  • 3
  • 30
  • 44