2013-02-03 6 views
20

2つのボタンがあり、開始と停止を意味する簡単なJavaFX 2アプリケーションがあります。開始ボタンをクリックすると、バックグラウンドスレッドを作成して、何らかの処理を行い、進行中のUI(例えばプログレスバー)を更新したいと考えています。停止ボタンをクリックすると、スレッドを終了します。JavaFXのマルチスレッドで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.logSystem.out.println

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

答えて

22

TaskRunnableを実装していますので、handler.run();に電話すると、実際にはcallメソッドがUIスレッドで実行されます。それはUIをハングします。

executorを使用して、または単にnew Thread(handler).start();を呼び出して、バックグラウンドスレッドでタスクを開始する必要があります。

これはthe javadocまたはJavaFX concurrency tutorialに説明されています(あまり明確ではないかもしれません)。

+3

私は十分な仲間に感謝することはできません。 –

+0

もう1つ質問があります。メインスレッドのラベルをタスクスレッドの進行状況で更新したいと思います。このために、このコードをタスク 'mainProg.updateStatus(i);'とメインプログラム 'public void updateStatus(int i){this.label.setText(i));で使用します。 } '。これはうまくいくのですか、UIを更新するために 'MainProg.updateStatus()'の 'platform.runLater()'を使うべきでしょうか? –

+1

はい、runLaterを使用してUIスレッドで実行する必要があります。または、UIスレッドで実行されるupdateProgressメソッド(チュートリアルの例3を参照)を使用することもできます。 – assylias

関連する問題