Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stop/cancel SwingWorker thread?

You need to keep a reference to your SwingWorker, then you use that reference to cancel the worker thread.

MySwingWorker myWorker = new MySwingWorkerClass(args).execute();

button.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) 
    {
        // Stop the swing worker thread
        myWorker.cancel(true);
    }
});

Here is a full example:

enter image description here

public class WorkerDemo extends JFrame {
    private boolean isStarted = false;
    private JLabel counterLabel = new JLabel("Not started");
    private Worker worker = new Worker();
    private JButton startButton = new JButton(new AbstractAction("Start") {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            if(!isStarted) { 
                worker.execute();
                isStarted = false;
            }
        }

    });
    private JButton stopButton = new JButton(new AbstractAction("Stop") {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            worker.cancel(true);
        }

    });

    public WorkerDemo() {

        add(startButton, BorderLayout.WEST);
        add(counterLabel, BorderLayout.CENTER);
        add(stopButton, BorderLayout.EAST);
        pack();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
    }

    class Worker extends SwingWorker<Void, Integer> {

        int counter = 0;

        @Override
        protected Void doInBackground() throws Exception {
            while(true) {
                counter++;
                publish(counter);
                Thread.sleep(60);
            }
        }

        @Override
        protected void process(List<Integer> chunk) {

            // get last result
            Integer counterChunk = chunk.get(chunk.size()-1);

            counterLabel.setText(counterChunk.toString());
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new WorkerDemo();
            }

        });
    }

}

You need to periodically check its cancelled flag (i.e. isCancelled()). SwingWorker leaves how to handle the interrupt up to you.

For more information, see Cancelling Background Tasks.


you can try overidding the done() method and put it in try catch and catch the java.util.concurrent.CancellationException. Something like

. . .

@Overide
done() {
   try {
     get();
   } catch (CancellationException e) {
       // Do your task after cancellation
   }
}

. . .


I think you have to restart the counter after every stop.

For startButton, you have to have worker restarted as in

private JButton startButton = new JButton(new AbstractAction("Start") {

        @Override
        public void actionPerformed(ActionEvent arg0) {
            if(!isStarted) { 
                worker = new Worker();     // New line
                worker.execute();
                isStarted = false;
            }
        }
    });

To stop you can use

worker.setStopFlag(); // in stopButton actionPerformed block.

in Worker class private boolean stopFlag = false;

and add

if( stopFlag)
break;

after Thread.sleep(60); and finally put setter for stopFlag at the end of Worker class as

void setStopFlag(){
    stopFlag = true;
}

By the way, you can use cancel(true) if you want to have exception exit.