我有以下情况:
向用户显示登录屏幕
用户将尝试登录
javafx任务将开始与服务器通信。
当通信工作在后面时,将向用户显示一个不确定的进度条(从主线程调用)。
如果登录凭据正确,则会向用户移动设备发送OTP消息。
将显示OTP对话框(javafx阶段),用户应输入收到的OTP(主线程应等到获得此OTP然后才能继续处理)。
不幸的是,我遇到了很多问题,如下所示:
1 - 当前OTP对话框从后台通信线程通过Platform.runLater调用,但主线程继续运行而不等待OTP。
我该如何完成这项任务?????
答案 0 :(得分:0)
如果你运行一个新线程与服务器通信,你可以简单地让主线程等待,直到这个线程结束Thead.join()
join方法允许一个线程等待另一个线程的完成。 如果t是其当前正在执行其线程的Thread对象,则
t.join();
导致当前线程暂停执行,直到t的线程终止。连接过载允许程序员指定等待期。但是,与sleep一样,join依赖于操作系统进行计时,因此您不应该假设连接将等待您指定的时间。
与sleep一样,join通过退出InterruptedException来响应中断。
如果你有一个线程池(或者有其他理由不完成你的后台thead),那么我们谈论线程同步。请查看Phaser或CyclicBarrier。
一种同步辅助工具,允许一组线程全部等待彼此到达公共障碍点。 CyclicBarriers在涉及固定大小的线程方的程序中很有用,这些线程必须偶尔等待彼此。屏障称为循环,因为它可以在等待线程释放后重新使用。
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();
}
}
答案 1 :(得分:0)
您的应用程序需要编写大量代码,因此这里将提供一个主要使用单词的解决方案。
~~&gt;使用JavaFX服务
JavaFX支持Service类。您必须创建一个扩展Service的类,如下所示:
public ServerWork extends Service<Boolean>{...}
关于如何使用服务的
这个类将有一个名为startService()的方法,它将启动CountDownLatch,因此调用此方法的主线程将冻结,直到Service完成。
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
~~&GT;最后是用户界面
在您的舞台上,您将拥有ProgressIndicator
或ProgressBar
,您将把它的进度属性绑定到服务的progressProperty,如下所示:
progressIndicator.progressProperty().bind(ServerWorkInstance().progressProperty();
要完全理解上面的内容,请阅读上面给出的链接并搜索一些教程。