Остановить / отменить тему SwingWorker? - PullRequest
26 голосов
/ 10 ноября 2011

Я пытаюсь выяснить, как остановить запуск потока SwingWorker при нажатии кнопки.Я оглядывался по сторонам, и у меня возникли некоторые проблемы, когда я решил, как это сделать.На данный момент это то, что у меня есть:

new MySwingWorkerClass(args).execute();

Я создаю кнопку, которую хочу использовать для остановки потока:

button = new JButton("Stop");
button.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) 
        {
        // Stop the swing worker thread
        }
});

Я уже посмотрелвокруг в поисках ответа, пока мне удалось найти метод отмены.Я не понимаю, как использовать это, чтобы остановить мой рабочий качели все же.Я попробовал следующее, но это не сработало:

SwingWorker.cancel(true);

Ответы [ 4 ]

39 голосов
/ 07 февраля 2012

Вам нужно сохранить ссылку на вашего SwingWorker, затем эту ссылку вы используете для отмены рабочего потока.

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

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

Вот полный пример:

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

        });
    }

}
14 голосов
/ 10 ноября 2011

Вам необходимо периодически проверять его отмененный флаг (т.е. isCancelled()). SwingWorker оставляет за вами право обрабатывать прерывание.

Для получения дополнительной информации см. Отмена фоновых задач .

2 голосов
/ 05 февраля 2013

Я думаю, вам нужно перезапускать счетчик после каждой остановки.

Для startButton необходимо перезапустить работника, как в

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

Для остановки вы можете использовать

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

в рабочем классе приватный логический stopFlag = false;

и добавьте

if( stopFlag)
break;

после Thread.sleep (60); и, наконец, поместите установщик для stopFlag в конце класса Worker как

void setStopFlag(){
    stopFlag = true;
}

Кстати, вы можете использовать отмена (true), если хотите получить исключение.

2 голосов
/ 14 февраля 2012

вы можете попробовать переопределить метод done () и поместить его в try catch и перехватить исключение java.util.concurrent.CancellationException.Что-то вроде

.,.

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

.,.

...