web-dev-qa-db-ja.com

JavaFXのマルチスレッドでUIがハングする

スタートとストップを言う2つのボタンがあるシンプルなJavaFX2アプリがあります。スタートボタンがクリックされたときに、処理を実行し、進行中にUI(プログレスバーなど)を更新するバックグラウンドスレッドを作成したいと思います。停止ボタンがクリックされたら、スレッドを終了させたいです。

ドキュメントから収集したjavafx.concurrent.Taskクラスを使用してこれを実行しようとしましたが、これには問題なく機能します。しかし、[スタート]をクリックすると、UIは通常のままではなく、フリーズ/ハングします。

彼女は、ボタンを表示するためのメインの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クラスのコードは次のとおりです。

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

非常に単純ですが、コンソールメッセージは引き続き表示されますが、[スタート]ボタンをクリックするたびにUIがハングします(Logger.logは単にSystem.out.printlnを実行します)

私は何が間違っているのですか?

22
Click Upvote

TaskRunnableを実装しているため、handler.run();を呼び出すと、実際にはUIスレッドでcallメソッドを実行します。それはUIをハングさせます。

エグゼキュータを介して、または単にnew Thread(handler).start();を呼び出すことにより、バックグラウンドスレッドでタスクを開始する必要があります。

これは、 javadoc または JavaFX同時実行チュートリアル で説明されています(あまり明確ではないかもしれません)。

26
assylias