繁体   English   中英

使用2个按钮启动和停止JavaFX后台线程

[英]Start and stop JavaFX background thread with 2 buttons

我正在尝试制作一个简单的UI来启动硒测试,该硒测试能够启动后台线程,该后台线程在按下“开始”按钮时启动浏览器,并在按下“停止”按钮时停止该线程并关闭它。 不幸的是,当我在启动后单击停止时,它不起作用。 如果结束,则无法重新启动线程。 我将如何进行更新,以便使它提交可以由“停止”按钮停止的新线程。

        package application;

import org.openqa.selenium.WebDriver;

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;


public class Main extends Application {
    Stage window;
    GridPane grid;
    public void start(Stage primaryStage) {

        /*
         * Set up the stage
         */
        window = primaryStage;
        window.setTitle("URL LOADER - V1");
        grid = new GridPane();
        grid.setPadding(new Insets(10,10,10,10));
        grid.setVgap(8);
        grid.setHgap(10);
        window.setResizable(false);

        /*
         * URL input
         */
        Label URLLabel = new Label("URL");
        GridPane.setConstraints(URLLabel,0,0);
        TextField URLTextField = new TextField();
        URLTextField.setPromptText("https://www.google.com");
        GridPane.setConstraints(URLTextField,1,0);

        /*
         * Create Buttons
         */
        Button buttonStart = new Button("Create");
        GridPane.setConstraints(buttonStart,1,6);
        Button buttonStop = new Button("Stop");
        GridPane.setConstraints(buttonStop,1,8);

        grid.getChildren().addAll(URLLabel,URLTextField, buttonStart, buttonStop);

        /*
         * Create the scene
         */
        Scene scene = new Scene(grid, 300, 300);
        window.setScene(scene);
        window.show();

        Task<Void> task = new Task<Void>(){
            @Override
            protected Void call() {
                new VisitPage().Start(this,URLTextField.getText());;
                return null;
            }
        };

        buttonStart.setOnAction(new EventHandler<ActionEvent>() {
        /*
         * Start Button Clicked
         */
        public void handle(ActionEvent event) {

            new Thread(task).start();

        }

    });

        buttonStop.setOnAction(new EventHandler<ActionEvent>() {
            /*
             * Start Button Pressed
             */
            public void handle(ActionEvent event) {
                System.out.println("Stop Pressed");

            }
        });

    }

    public class VisitPage {
        private String URL;
        Browser BrowserFactory;
        ThreadLocal<WebDriver> drivers;
        WebDriver Browser;
        public void Start(Task<Void> task, String URL) {
            while (true) {
                if (task.isCancelled())
                {
                        System.out.println("Canceling...");
                        System.out.println("Stop Pressed");
                        Browser.close();
                        Browser.quit();
                        BrowserFactory.CloseDriver(drivers);
                        task.cancel();
                }
                else
                {
            /*
             * Create Browser Factor to make ThreadLocal Browsers
             */
            BrowserFactory = new Browser(1, 1);
            drivers = BrowserFactory.SpawnBrowser();
            /*
             * Grab a Browser
             */
            Browser = BrowserFactory.SpawnDriver(drivers);
            /*
             * Visit and scrape
             */
            Browser.get(URL);
            /*
             * Wait 5 Seconds before closing
             */
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            Browser.close();
            Browser.quit();
            BrowserFactory.CloseDriver(drivers);
                 }

             }
        }

    }


    public static void main(String[] args) {
        launch(args);
    }
}

根据文件

与FutureTask一样,Task是单发类,不能重用。 请参阅服务以获取可重复使用的工作人员。

因此,您必须为每次运行创建新任务。 因此,我在Main中将任务添加为字段:

Stage window;
GridPane grid;
Task<Void> task;

然后,在单击开始按钮时创建任务:

buttonStart.setOnAction(new EventHandler<ActionEvent>() {
    /*
     * Start Button Clicked
     */
    @Override
    public void handle(ActionEvent event) {
        if(task != null) {
            System.out.println("Task already running");
            return;
        }
        task = new Task<Void>() {
            @Override
            protected Void call() {
                new VisitPage().start(this, URLTextField.getText());
                ;
                return null;
            }
        };
        Thread thread = new Thread(task);
        thread.setDaemon(true);
        thread.start();
    }
});

在停止按钮上单击,您必须取消任务:

buttonStop.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            if(task == null) {
                System.out.println("Task not running");
                return;
            }
            System.out.println("Stop Pressed");
            task.cancel();
            task = null;
        }
    });

这将无济于事,因为取消任务是您的责任,而您并没有结束无限循环。 因此,您的VisitPage应该如下所示(我跳过了测试详细信息,因为我没有在类路径上使用它们):

public class VisitPage {
    public void start(Task<Void> task, String URL) {
        while (!task.isCancelled()) {
            System.out.println("Running test");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("Test run ended");
        }
        System.out.println("Canceling...");
        System.out.println("Stop Pressed");
        return;
    }
}

一些小要点:

从技术task.cancel()如果您不捕获线程正在睡眠时引发的InterruptedException ,则task.cancel()有时会终止线程。

我不确定您的代码是如何编译的,但是我必须使某些变量最终化,以便可以在处理程序中使用它们:(没关系,从Java SE 8开始,局部变量可以有效地最终化)

final TextField URLTextField = new TextField();
//...
final  Task<Void> task = new Task<Void>(){
//...

我会将创建的线程定义为守护程序,这样当您关闭UI而不停止测试时它将不会继续运行:

Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();

我还重命名了Start方法来start

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM