JavaFX TaskWorker не запускается

Вопрос или проблема

Я разрабатываю небольшое настольное приложение на JavFXML, которое включает в себя TaskWorker. Цель заключается в том, чтобы запустить task worker при нажатии на кнопку, но ничего не происходит, и task worker не вызывается. Код обработки клика мыши выглядит так:

public class TableViewController implements Initializable{
    ....

 @FXML private void handleGoButton () {
    TaskWorker taskworker = new TaskWorker(50);  
    new Thread(taskworker).start(); 
  }

Изначальная цель заключалась в том, чтобы запустить индикатор прогресса и операции копирования файлов внутри task worker, но чтобы попытаться понять проблему, я убрал большую часть этого кода и заменил его простым циклом, который выводит значение индекса. Таким образом, task worker выглядит так:

public class TaskWorker extends Task<Void> {
  public int value;  
  
  public TaskWorker (int value) {
    this.value = value;
    System.out.println("Value = " + this.value );
  }
  
  @Override
  protected Void call() throws Exception {
    int pind = 1;
    String bkpdate = new ValiDate().gettodaysSwedishDate(); 
    for (int i=0; i < this.value; i++){
      System.out.println("Value of i = " + i );   
      Thread.sleep(400); 
    }
    return null;
  }
}

При нажатии мыши я ожидал увидеть вывод, подтверждающий, что конструктор в TaskWorker получил переданное значение, и вывод, показывающий значение индекса до переданного значения. Task worker действительно получает значение в конструкторе:

compile:
run:
Value = 50
BUILD SUCCESSFUL (total time: 18 seconds)

но метод call() никогда не запускается.

Ответ или решение

Судя по вашему описанию, проблема заключается в том, что вы пытаетесь запустить задачу TaskWorker, создавая новый поток непосредственно из метода обработки нажатия кнопки. В JavaFX все обновления пользовательского интерфейса должны выполняться в его основном потоке (говне. thread safe), и запуск задач в отдельных потоках, как в вашем случае, может вызвать проблемы.

Правильный способ запуска Task в JavaFX – это использовать встроенные механизмы, которые уже работают с потоками, такие как Task и Service. Вместо создания нового потока для выполнения задачи, следует использовать сам объект Task для выполнения асинхронной работы.

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

public class TableViewController implements Initializable {

    @FXML
    private ProgressIndicator progressIndicator; // Для отображения индикатора прогресса
    @FXML
    private Button goButton; // Кнопка для запуска задачи

    @FXML
    private void handleGoButton() {
        TaskWorker taskWorker = new TaskWorker(50);

        // Указываем, что обновления состояния задачи будут обрабатываться здесь
        taskWorker.setOnSucceeded(e -> {
            System.out.println("Задача завершена успешно!");
            progressIndicator.setVisible(false); // Скрыть индикатор прогресса
        });

        taskWorker.setOnFailed(e -> {
            System.out.println("Задача завершилась с ошибкой!");
            progressIndicator.setVisible(false); // Скрыть индикатор прогресса
        });

        taskWorker.setOnRunning(e -> {
            progressIndicator.setVisible(true); // Показать индикатор прогресса
        });

        // Запускаем задачу на новом потоке
        new Thread(taskWorker).start();
    }
}

public class TaskWorker extends Task<Void> {
    public int value;

    public TaskWorker(int value) {
        this.value = value;
        System.out.println("Value = " + this.value);
    }

    @Override
    protected Void call() throws Exception {
        for (int i = 0; i < this.value; i++) {
            System.out.println("Value of i = " + i);
            Thread.sleep(400); // Эмуляция длительной работы
            updateProgress(i + 1, this.value); // Обновление прогресса (если нужно)
        }
        return null; // Успешное завершение
    }
}

Основные изменения:

  1. Использование методов setOnSucceeded, setOnFailed и setOnRunning: Эти методы обеспечивают обработку событий, связанных с состоянием задачи, позволяя вам управлять прогрессом и выводить сообщения, когда задача выполнена или завершилась с ошибкой.

  2. Индикатор прогресса: Добавьте ProgressIndicator в ваш интерфейс, чтобы пользователь видел, что процесс выполняется. В коде я добавил управление его видимостью.

  3. Обновление прогресса: Вы можете обновлять прогресс выполнения задачи с помощью updateProgress(), что позволит вашему интерфейсу отображать соответствующий прогресс.

После внесения этих изменений ваша задача должна корректно запускаться, а вывод в консоль должен отображаться по мере выполнения цикла в call().

Оцените материал
Добавить комментарий

Капча загружается...