0

I have the following scenario:

  1. A log in screen appears to the user

  2. The user will tries to login

  3. A javafx task will start to communicate with the server.

  4. While the communication works on behind, an indeterminate progress bar will be shown to the user (this called from the main thread).

  5. If the login credentials are correct, an OTP message will be sent to the user mobile.

  6. An OTP dialog (javafx stage) will be shown, and the user should enter the OTP received (The main thread should wait until it gets this OTP then can continue processing).

Unfortunately, I faced many problems with this, as the following:

1 - Currently the OTP dialog called from the background communication thread through Platform.runLater, but the main thread continue running without waiting the OTP.

How can I accomplish this task?????

ManKeer
  • 543
  • 2
  • 6
  • 27
  • For making a background thread wait for user input from the FX Application Thread, see http://stackoverflow.com/questions/14941084/javafx2-can-i-pause-a-background-task-service – James_D Aug 29 '16 at 10:23
  • @James_D, thank you very much this exactly what I was looking for, and I just want to add this comment to refer for that link. – ManKeer Aug 29 '16 at 15:26
  • I'll mark this as a duplicate, if that completely answers the question. It will make it easier for others searching for the same thing to find the solution. – James_D Aug 29 '16 at 15:45

2 Answers2

0

If you run a new thread to communicate with server you can simply make main thread wait till this thread ends using Thead.join()

The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,

t.join();

causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.

If you have a thread pool(or have another reason to not finalise your background thead) then we speaking about threads synchronisation. Look at Phaser or CyclicBarrier.

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.

 class Solver {
   final int N;
   final float[][] data;
   final CyclicBarrier barrier;

   class Worker implements Runnable {
     int myRow;
     Worker(int row) { myRow = row; }
     public void run() {
       while (!done()) {
         processRow(myRow);

         try {
           barrier.await();
         } catch (InterruptedException ex) {
           return;
         } catch (BrokenBarrierException ex) {
           return;
         }
       }
     }
   }

   public Solver(float[][] matrix) {
     data = matrix;
     N = matrix.length;
     barrier = new CyclicBarrier(N,
                                 new Runnable() {
                                   public void run() {
                                     mergeRows(...);
                                   }
                                 });
     for (int i = 0; i < N; ++i)
       new Thread(new Worker(i)).start();

     waitUntilDone();
   }
 }
Konstantin Labun
  • 3,688
  • 24
  • 24
  • The problem is the OP is not waiting for a Thread to finish; he's waiting for one particular block of code to complete on the FX Application Thread. So `join()` won't work here. – James_D Aug 29 '16 at 12:54
0

Your app requires a lot code to be written so here will be provided a solution mostly with words.

~~>Using JavaFX Service

JavaFX supports Service class.You have to make a class that extends Service like this:

public ServerWork extends Service<Boolean>{...}

Read this on how to use Service

This class will have a method called startService( ) which will start a CountDownLatch so the main thread by calling this method will freeze until Service is done.

class

......

private CountDownLatch countDown;


//Constructor
public ServerWork( ){


 //if service succeeded
 onSucceed(f->{ 
     .....
     done();
 };


//if Service failed 
  onFailed(f->{   
   ..... 
    done();
   };


//if Service cancelled 
   onCancelled(f->{
     .....
      done();
   };

}

/** Start the Service */
 public void startService ( ){

  //Service is not Running
  if(!isRunning()){

    countDown= new CountDownLatch(1);
    countDown.await();

    reset();
    start();

   }

 }

 /** Service has finished failed or not or cancelled */
 private void done( ){ 
   //unbind the progress bar or progress indicator here

   progressbar.progressProperty().unbind();

  //countDown so main thread is released
  countDown.countDown( );

}



//..@Override createTask() and update Service progress 

~~> Finally the User Interface

In your stage you will have a ProgressIndicator or ProgressBar and you will bind it's progress Property to the progressProperty of the Service like this:

progressIndicator.progressProperty().bind(ServerWorkInstance().progressProperty();

To fully understand the above read the links given above and search some tutorials.

GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93