Что я сделал не так, когда хотел остановить SwingWorker в этом случае?

public class Worker extends SwingWorker<Integer, String> {
private JLabel screen;

    public Worker(JLabel screen) {
        this.screen = screen;
    }

    @Override
    protected Integer doInBackground() throws Exception {
        for (; ; ) {
            publish(String.valueOf(Calendar.getInstance().getTimeInMillis()));
        }
    }

    @Override
    protected void process(List<String> chunks) {
        screen.setText(chunks.get(0));
    }
}

И в форме:

    public class Form extends JPanel{
    private JButton startButton;
    private JPanel rootPanel;
    private JButton stopButton;
    private JLabel screen;
    private Worker worker;

    public Form() {
        startButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                worker = new Worker(screen);
                worker.execute();
            }
        });
        stopButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                worker.cancel(true);
                System.out.println(worker.isDone());
                System.out.println(worker.isCancelled());
            }
        });
    }

    private void createUIComponents() {
        rootPanel = this;
    }
}

Я пытался написать тот же код с Tread, но он тоже не работает. И вывод консоли после нажатия на stopButton:

true

true

Итак, рабочий выполнен, но программа продолжает показывать миллисекунды. Что такое посмертная жизнь? И в случае использования Thread то же самое: метод isAlive() возвращает «false».

ваш цикл никогда не завершается, поэтому рабочий никогда не останавливается. Вместо for( ; ; ) попробуйте while (!Thread.interrupted()) (метод публикации не проверяет)

user85421 19.03.2019 19:25

SwingWorker должен вызвать метод isCancelled(), чтобы определить, был ли рабочий процесс отменен, а затем выйти из цикла while в методе doInBackground().

Palamino 19.03.2019 21:12
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
2
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по вашему коду, похоже, что вам нужен рабочий процесс с циклом, который будет продолжать работать до тех пор, пока главный поток не сообщит ему о прекращении работы, что и делается с помощью worker.cancel(true);. Проблема в том, что вы отменяете его, но ничего не делаете, чтобы сигнализировать самому циклу о прекращении итерации. Чтобы исправить это, вы должны изменить

for (; ; ) {
    publish(String.valueOf(Calendar.getInstance().getTimeInMillis()));
}

к

while(!isCancelled()){
    publish(String.valueOf(Calendar.getInstance().getTimeInMillis()));
}

Обратите внимание на формулировку «isCancelled» из документации по Java:

isCancelled()

Returns true if this task was canceled before it completed normally. Since the loop never closes on its' own, it will never complete normally.

Другие вопросы по теме