java JavaFX 中的多线程挂起 UI

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14674274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 17:02:59  来源:igfitidea点击:

Multithreading in JavaFX hangs the UI

javamultithreadingjavafx-2javafx

提问by Click Upvote

I have a simple JavaFX 2 app, with 2 buttons, saying Start and Stop. When the start button is clicked, I want to create a background thread which will do some processing and update the UI (e.g a progress bar) as it goes along. If the stop button is clicked, I want the thread to terminate.

我有一个简单的 JavaFX 2 应用程序,有 2 个按钮,分别是启动和停止。单击开始按钮时,我想创建一个后台线程,该线程将执行一些处理并在执行过程中更新 UI(例如进度条)。如果单击停止按钮,我希望线程终止。

I've tried to do this using the javafx.concurrent.Taskclass which I gathered from the documentation would work fine for this. But whenever I click Start, the UI freezes/hangs rather than staying normal.

我尝试使用javafx.concurrent.Task我从文档中收集的类来做到这一点,对此我可以很好地工作。但是每当我单击“开始”时,UI 都会冻结/挂起而不是保持正常。

Her's the code from the main Myprogram extends Applicationclass for showing the buttons:

她是来自主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.
}

Here's the code of MyProcessorclass:

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

Pretty simple, but the UI hangs whenever I click the Start button, though the console messages continue to get displayed (Logger.logsimply does System.out.println)

非常简单,但是每当我单击“开始”按钮时 UI 都会挂起,尽管控制台消息会继续显示(Logger.log只是这样做System.out.println

What am I doing wrong?

我究竟做错了什么?

回答by assylias

Taskimplements Runnable, so when you call handler.run();you actually run the callmethod in the UI Thread. That will hang the UI.

Task实现Runnable,因此当您调用时,handler.run();您实际上是call在 UI 线程中运行该方法。这将挂起 UI。

You should start the task in a background thread, either via an executor or simply by calling new Thread(handler).start();.

您应该在后台线程中启动任务,通过执行程序或简单地调用new Thread(handler).start();.

This is explained (maybe not very clearly) in the javadocor in the JavaFX concurrency tutorial.

这在javadocJavaFX concurrency tutorial 中有解释(可能不是很清楚)。