Запустите службу в фоновом потоке

Могу ли я запустить службу в фоновом потоке?

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

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

Как я могу достичь желаемого результата?

1 ответ

Решение

Хорошо... Вот готовый код: https://mega.nz/#!yUsjgJyZ!DHfuBqsujAHurS-pQ_W5y8BAflOtvxsm48goRPkDsxA

Во-первых, я хочу сказать вам, какова моя цель:

Когда я запускаю программу, я хочу, чтобы индикатор выполнения находился в неопределенном состоянии. После нажатия на кнопку, я хочу, чтобы индикатор выполнения отражал прогресс службы. После завершения службы, я хочу, чтобы индикатор выполнения был завершен (100%).

Вот что я нашел. Похоже, сервис автоматически запускает свою задачу в фоновом потоке. Я построил программу "песочницы", где я играл со службами и индикатором выполнения. Программа состояла из индикатора выполнения, двух текстовых полей с двумя кнопками над ними. Первая кнопка может запустить service_countTo100, а вторая кнопка может запустить service_getActualCount.

Теперь в файле fxml я установил индикатор выполнения в неопределенное состояние по умолчанию. После нажатия кнопки 1 начался отсчет (отображается в text_field1), и индикатор выполнения изменился в соответствии с фактическим прогрессом. После нажатия кнопки 2 фактическое значение счетчика отображается в поле text_field2. И тут возникают некоторые проблемы. Чтобы продемонстрировать проблемы, я покажу вам исходный код службы:

// Create the service
public static Service<Integer> serviceTo100 = new Service<Integer>() {
    @Override
    protected Task<Integer> createTask() {
        Task<Integer> taskTo100 = new Task<Integer>() {
            @Override protected Integer call() throws Exception {

                int iterations;
                updateProgress(-1, 100);
                for (iterations = 0; iterations < 100; iterations++) {
                    if (isCancelled()) {
                        updateMessage("Cancelled");
                        break;
                    }

                    updateMessage("Iteration " + iterations);
                    updateProgress(iterations, 100);

                    // Now block the thread for a short time, but be sure
                    // to check the interrupted exception for cancellation!
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException interrupted) {
                        if (isCancelled()) {
                            updateMessage("Cancelled");
                            break;
                        }
                    }
                }

            //udpateProgress(100, 100);    
            return iterations;
            }
        };
    return taskTo100;
    }
};

Как видите, есть простой цикл, который насчитывает от 0 до 100, а также есть updateProgress(iterations, 100); заявление, которое обновляет прогресс. Этот сервис находится в Services учебный класс. В FXMLDocumentController.java вызывается метод runService(Service service) определяется как это:

public void runService(Service service){

        service.start();
        progressBar.progressProperty().bind(service.progressProperty());

        service.setOnSucceeded((event) -> {
            service.reset();
            progressBar.progressProperty().unbind();
            progressBar.setProgress(1);                                
        });
}

initialize выглядит так:

@Override
public void initialize(URL url, ResourceBundle rb) {
    btn_start1.setOnAction((event) -> {

        Service service = Services.serviceTo100;
        runService(service);
        txt_field1.textProperty().bind(service.messageProperty());                     
        System.out.printf("something\n");  

    });
    .
    .
    .
    }//end of initialize

Теперь самое интересное (по крайней мере для меня, новичка) вступает в игру.

В определении сервиса вы можете заметить закомментированную строку //updateProgress(100,100), Это была моя попытка установить индикатор выполнения в завершенное состояние, когда подсчет остановился. Но ява проигнорировала эту строчку. Я пытался поставить System.out.print("Something"); и это сработало, но updateProgress(100, 100) не сделал. Когда подсчет завершился, индикатор выполнения был установлен в состояние по умолчанию, определенное в файле fxml, которое было неопределенным.

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

Даже если задача больше не существует, вы не можете установить прогресс ограниченного индикатора выполнения с помощью setProgress(double double) метод. Сначала нужно отсоединить его.

Теперь я получил то, что мне было нужно:

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

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