【问题标题】:JavaFX - How to pause a background Service with UI controller event?JavaFX - 如何使用 UI 控制器事件暂停后台服务?
【发布时间】:2014-09-21 13:32:46
【问题描述】:

对于 JavaFX UI 控制器事件,我想暂停后台服务,该服务以该 UI 控制器开始(如以下代码所示)。

我发现了一个类似的帖子JavaFX2: Can I pause a background Task / Service。但是在那篇文章中,它将提供使用自己的事件暂停服务的解决方案,而不是使用外部 UI 控制器触发的事件。

实际上在这种情况下,我似乎必须设置服务的内部状态以使其暂停,但工作接口不包含这样的状态。举个例子,我们可以强制让服务失败,它的状态为失败等。

谢谢。

UI 控制器类

public class CommandController implements Initializable {

 private CommandService commandService;
 private ExecutorService sequentialServiceExecutor;
 private List<IOCommandService> servicePool = new ArrayList<>();

 @Override
 public void initialize(URL location, Resources resources) {

   doProceedInitialSteps(); 
 }

 private void doProceedInitialSteps() { 

   // Select available IOCommands 
   List<IOCommand> commandList = commandService.getCommands();

   // Initialised ExecutorService on sequential manner
   sequentialServiceExecutor = Executors.newFixedThreadPool(
                1,
                new ServiceThreadFactory()
   );

   for (final IOCommand command : commandList) { 

        IOCommandService service = new IOCommandService(command, this);

        service.setExecutor(sequentialServiceExecutor);

        service.setOnRunning(new EventHandler<IOCommand>() { }

        service.setOnSucceeded(new EventHandler<IOCommand>() { }

        service.setOnFailed(new EventHandler<IOCommand>() { }

        service.start();

        servicePool.add(service);       
   }

 }

 @FXML
 public void onCancel() {

   // TODO: Need to pause current executing IOCommandService until receive the user response from the DialogBox

   // Unless pause current executing IOCommandService, that will over lap this dialog box with IOCommandService related dialog boxes etc  

   Dialogs.DialogResponse response = Dialogs.showWarningDialog();

   if(response.toString.equals("OK") {

   }
 }

}

服务类

public class IOCommandService extends Service<IOCommand> {

  private IOCommand command;
  private CommandController controller;

  public IOCommandService (IOCommand command, CommandController controller) {
     this.command = command;
     this.controller = controller;
  }

  @Override
  protected Task<IOCommand> createTask() {

    return new Task<IOCommand>() {

        @Override
        protected Integer call() throws Exception {

         // Execute the IO command by,
         // 1) updating some UI components (label, images etc) on CommandController
         // 2) make enable popup some Dialog boxes for get user response  

         return command;            
        }
    }
  }    
}

【问题讨论】:

    标签: java multithreading service concurrency javafx


    【解决方案1】:

    Hej Channa,

    这是一个示例,您可以如何“暂停”您的 Service 并在关闭 Dialog 后恢复它。

    这是 FXML ;)

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import java.lang.*?>
    <?import java.util.*?>
    <?import javafx.scene.*?>
    <?import javafx.scene.control.*?>
    <?import javafx.scene.layout.*?>
    
    <AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml" fx:controller="de.professional_webworkx.stopservice.FXMLController">
        <children>
            <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
            <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
        </children>
    </AnchorPane>
    

    主应用程序

    import javafx.application.Application;
    import static javafx.application.Application.launch;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    
    public class MainApp extends Application {
    
        @Override
        public void start(Stage stage) throws Exception {
            Parent root = FXMLLoader.load(getClass().getResource("/fxml/Scene.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setTitle("JavaFX and Concurrency");
            stage.setScene(scene);
            stage.show();
        }
    
    
        public static void main(String[] args) {
            launch(args);
        }
    
    }
    

    控制器

    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.application.Platform;
    import javafx.concurrent.Worker;
    import javafx.event.ActionEvent;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.Scene;
    import javafx.scene.control.Label;
    import javafx.stage.Stage;
    
    public class FXMLController implements Initializable {
    
        @FXML
        private Label label;
        private MyService ms;
        @FXML
        private void handleButtonAction(ActionEvent event) {
            onCancel();
        }
    
        @Override
        public void initialize(URL url, ResourceBundle rb) {
            ms = new MyService();
            Platform.runLater(() -> {
                ms.start();
            });
        }    
    
        public void onCancel() {
    
            if(ms.getState().equals(Worker.State.RUNNING)) {
                ms.cancel();
            }
            Scene s = new Scene(new Label("Dialog"), 640, 480);
            Stage dialog = new Stage();
            dialog.setScene(s);
            dialog.showAndWait();
    
            if(!dialog.isShowing()) {
                ms.resume();
            }
    
    
        }
    }
    

    还有 MyService 类

    我在控制台上运行一个 for 循环并打印出数字。如果我调用MyServicepause() 方法,我调用cancel() 它和restart() 它调用resume() 方法。 线程.sleep(2000L);我只是添加来模拟长时间运行的Task

    import javafx.concurrent.ScheduledService;
    import javafx.concurrent.Service;
    import javafx.concurrent.Task;
    
    /**
     *
     * @author Patrick Ott
     * @version 1.0
     */
    public class MyService extends ScheduledService<Void> {
    
        Task<Void> task;
        int n = 1000000000;
        @Override
        protected Task<Void> createTask() {
            return new Task() {
    
                @Override
                protected Object call() throws Exception {
                    for (int i = 0; i < n; i++) {
                        System.out.println("Halllo " + n);
                        Thread.sleep(2000);
                        n--;
                    }
                    return null;
                }
            };
        }
    
        public void pause() {
            this.cancel();
        }
    
        public void resume() {
            System.out.println("n="+n);
            this.restart();
        }
    }
    

    帕特里克

    【讨论】:

    • 嗨帕特里克!非常感谢您的反馈。但是按照这种逻辑,我们似乎无法暂停服务。这意味着“cancel()”方法不会暂停服务,它将终止服务的执行。并且“restart()”方法将取消任何当前正在运行的服务,并从头开始重新启动服务。当它聚集在一起时,似乎终止服务并从乞讨开始。
    • @Channa 也许您可以编辑您的问题并添加您在服务中运行的逻辑,并提示您必须同时运行多少个服务。这是一个有趣的问题..
    • 嗨帕特里克!感谢您的反馈。我刚刚更新了问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多