Подтвердить что ты не робот

Пользовательский интерфейс в многопоточности в JavaFX

У меня есть простое приложение JavaFX 2 с двумя кнопками, говорящее "Пуск и Стоп". Когда нажата кнопка запуска, я хочу создать фоновый поток, который будет выполнять некоторую обработку и обновлять пользовательский интерфейс (например, индикатор выполнения) по мере его продвижения. Если нажата кнопка остановки, я хочу, чтобы поток завершился.

Я попытался сделать это, используя класс javafx.concurrent.Task, который я собрал из документации, будет отлично работать для этого. Но всякий раз, когда я нажимаю кнопку "Пуск", пользовательский интерфейс зависает или зависает, а не остается нормальным.

Ее код из основного класса Myprogram extends Application для отображения кнопок:

public void start(Stage primaryStage)
{               
    final Button btn = new Button();
    btn.setText("Begin");

    //This is the thread, extending javafx.concurrent.Task :
    final MyProcessor handler = new MyProcessor();
    btn.setOnAction(new EventHandler<ActionEvent>()
    {
        public void handle(ActionEvent event)
        {                
           handler.run(); 
        }
    });

    Button stop = new Button();
    stop.setText("Stop");
    stop.setOnAction(new EventHandler<ActionEvent>()
        {
             public void handle(ActionEvent event)
             {
                handler.cancel();
             }
        }

    );
    // Code for adding the UI controls to the stage here.
}

Здесь код MyProcessor class:

import javafx.concurrent.Task;
public class MyProcessor extends Task
{   
    @Override
    protected Integer call()
    {
        int i = 0;
        for (String symbol : feed.getSymbols() )
        {
            if ( isCancelled() )
            {
                Logger.log("Stopping!");
                return i;
            }
            i++;
            Logger.log("Doing # " + i);
            //Processing code here which takes 2-3 seconds per iteration to execute
            Logger.log("# " + i + ", DONE! ");            
        }
        return i;
    }
}

Довольно просто, но пользовательский интерфейс зависает, когда я нажимаю кнопку "Пуск", хотя сообщения консоли продолжают отображаться (Logger.log просто делает System.out.println)

Что я делаю неправильно?

4b9b3361

Ответ 1

Task реализует Runnable, поэтому при вызове handler.run(); вы фактически запускаете метод call в потоке пользовательского интерфейса. Это повесит пользовательский интерфейс.

Вы должны запустить задачу в фоновом потоке либо через исполнителя, либо просто путем вызова new Thread(handler).start();.

Это объясняется (может быть, не очень четко) в javadoc или в учебнике JavaFX concurrency.