Search code examples
asynchronousconcurrencyjavafxrunnable

JavaFX show loading dialog for longer operations


I got some operations in my Controller class which could take some time. So I want to show a loading dialog while this operation is running.

I tried this:

Platform.runLater(new Runnable() {
  @Override
  public void run() {
     loadingDialog.show();
  }
});

Boolean opSuccess = myService.operate();

Platform.runLater(new Runnable() {
   @Override
   public void run() {
     loadingDialog.hide();
   }
});

if (opSuccess) {
   // continue
}

Now, the Problem is, the loadingDialog is never show. The UI only blocks for some time and than continues on "//continue".

So it seems, the runLater call is blocked by the blocking operation (operate)?

I also tried CoundDownLatch, to wait for loadingDialog.show() to complete, before running myService.operate(). But the latch.await() method never completes.

So my question is, how my I show the loadingDialog until myService.operate() finished and returned true or false? Do I have to put the operate() call into another thread and run it async or is there an easier way?

Thanks for help.


Solution

  • Are you sure your entire code does not run in the JavaFX Thread? Methods of your controller class usually do and I assume it due to your description.

    However, better use the Task class. Here you'll find a tutorial and a short snippet for your application:

    // here runs the JavaFX thread
    // Boolean as generic parameter since you want to return it
    Task<Boolean> task = new Task<Boolean>() {
        @Override public Boolean call() {
            // do your operation in here
            return myService.operate();
        }
    };
    
    task.setOnRunning((e) -> loadingDialog.show());
    task.setOnSucceeded((e) -> {
        loadingDialog.hide();
        Boolean returnValue = task.get();
        // process return value again in JavaFX thread
    });
    task.setOnFailed((e) -> {
      // eventual error handling by catching exceptions from task.get()  
    });
    new Thread(task).start();
    

    I assumed Java 8 and the possibility to use Lambda expressions. Of course it is possible without them.