Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading JavaFX任务正在等待另一个任务完成_Multithreading_Javafx_Concurrency - Fatal编程技术网

Multithreading JavaFX任务正在等待另一个任务完成

Multithreading JavaFX任务正在等待另一个任务完成,multithreading,javafx,concurrency,Multithreading,Javafx,Concurrency,我对Concurrency是个新手,我已经撞了好几次墙了。 代码几乎描述了一切,但只是为了澄清:用户按下按钮,应用程序向数据库发送查询,同时statusLabel设置为: 非常感谢 200ms 非常 200ms 非常 200ms 查询结果 我已经设法实现了这一点,但现在,我需要在另一个类中使用查询结果(若成功,将打开另一个窗口),但它永远不会这样做。我得出的结论是,它只是在任务完成之前检查结果,所以结果总是错误的,我不知道如何解决这个问题,所以另一个类在任务完成后检查条件 首先,我的授权类 pu

我对Concurrency是个新手,我已经撞了好几次墙了。 代码几乎描述了一切,但只是为了澄清:用户按下按钮,应用程序向数据库发送查询,同时statusLabel设置为:
非常感谢
200ms
非常
200ms
非常
200ms
查询结果

我已经设法实现了这一点,但现在,我需要在另一个类中使用查询结果(若成功,将打开另一个窗口),但它永远不会这样做。我得出的结论是,它只是在任务完成之前检查结果,所以结果总是错误的,我不知道如何解决这个问题,所以另一个类在任务完成后检查条件

首先,我的
授权

public class Authorization {
    private static String query = "";
    private static boolean isValid;
    private static Task<Void> task;

    public static void verifyLogin(String username, String password) throws SQLException{
        Status.get().unbind();
        isValid = false;
        task = new Task<Void>() {
            @Override
            protected Void call() throws SQLException {
               while(!isCancelled()) {
                   try {
                       updateMessage("Weryfikacja.");
                       Thread.sleep(200);
                       updateMessage("Weryfikacja..");
                       Thread.sleep(200);
                       updateMessage("Weryfikacja...");
                       Thread.sleep(200);

                       if(username.equals("") || password.equals("")) {
                           task.cancel();
                           updateMessage("Pola nie mogą być puste");
                       } else {
                           query = "SELECT login FROM users WHERE login = ?";
                           Query.execute(query, username);
                           if(!Query.resultSet.next()) {
                               task.cancel();
                               updateMessage("Nie ma takiego użytkownika");
                           } else {
                               query = "SELECT password FROM users WHERE login = ?";
                               Query.execute(query, username);
                               if(Query.resultSet.next()) {
                                   String passwordValue = Query.resultSet.getString(1);
                                   if(!password.equals(passwordValue)) {
                                       task.cancel();
                                       updateMessage("Podane hasło jest błędne");
                                   } else {
                                       task.cancel();
                                       updateMessage("");
                                       isValid = true;
                                   }
                               }
                           }
                       }
                   } catch(InterruptedException e) {
                       if(isCancelled()) {
                           break;
                       }
                   }
               }
               return null;
            }
        };
        Status.get().bind(task.messageProperty());
        new Thread(task).start();
    }

    public static boolean isValid() {
        return isValid;
    }
}
编辑# 很抱歉在
updateMessage()
中进行了润色

您的
verifyLogin()
方法只是在另一个线程中启动验证过程,然后立即退出。
isValid
标志将在该线程完成之前不会更改,这将在以后发生很多次。如果您想先执行验证过程,然后再执行其他操作,那么在
verifyLogin()
中管理线程是没有意义的

我真的不太明白你的代码应该做什么;您有一个
while(…)
循环,据我所知,它只能执行一次(因此是多余的)。您似乎还执行了两个基本相同的SQL查询。(第一个检查是否有具有特定条件的行,如果有,第二个检索该行。为什么不检索该行并检查它是否存在?)

我将对此进行重构,以便
validateLogin()
方法根本不处理线程,只返回验证结果(例如,一个状态字符串,但可能还有其他合适的内容)

现在,我将从
login()
方法管理线程。这样,您可以使用任务的
onSucceeded
处理程序在任务完成时执行代码:

private void login() {
    if( SqlConnection.isConnected()) {
        Task<String> verifyTask = new Task<String>() {
            @Override
            protected String call() throws SQLException {

                return Authorization.verifyLogin(loginInput.getText(), passwordInput.getText());
            }
        };

        // probably better to use a progress indicator or similar here, but:

        Animation animation = new Timeline(
            new KeyFrame(Duration.ZERO, e -> Status.get().set("Weryfikacja.")),
            new KeyFrame(Duration.millis(200), e -> Status.get().set("Weryfikacja..")),
            new KeyFrame(Duration.millis(400), e -> Status.get().set("Weryfikacja...")),
            new KeyFrame(Duration.millis(600)));
        animation.setCycleCount(Animation.INDEFINITE);


        verifyTask.setOnSucceeded(event -> {
            animation.stop();
            Status.get().set(verifyTask.getValue());
            if(Authorization.isValid()) { // or if (verifyTask.getValue().isEmpty()) 
                // go to next menu
            }
        });

        verifyTask.setOnFailed(event -> {
            animation.stop();
            verifyTask.getException().printStackTrace();
            Debug.log(verifyTask.getException().toString());
        }

        animation.play();
        new Thread(verifyTask()).start();
    }
}
private void login(){
if(SqlConnection.isConnected()){
任务验证任务=新任务(){
@凌驾
受保护的字符串调用()引发SQLException{
返回Authorization.verifyLogin(loginInput.getText(),passwordInput.getText());
}
};
//在此处使用进度指标或类似指标可能更好,但:
动画=新时间线(
新关键帧(Duration.ZERO,e->Status.get().set(“Weryfikacja”),
新的关键帧(Duration.millis(200),e->Status.get().set(“Weryfikacja..”),
新的关键帧(Duration.millis(400),e->Status.get().set(“Weryfikacja…”)),
新关键帧(持续时间.millis(600));
animation.setCycleCount(animation.unfinite);
verifyTask.setOnSucceeded(事件->{
动画。停止();
Status.get().set(verifyTask.getValue());
if(Authorization.isValid()){//或if(verifyTask.getValue().isEmpty())
//转到下一菜单
}
});
verifyTask.setOnFailed(事件->{
动画。停止();
verifyTask.getException().printStackTrace();
log(verifyTask.getException().toString());
}
动画。播放();
新线程(verifyTask()).start();
}
}

代码的可能重复非常令人困惑。在任务中执行
循环时,
的目的是什么?看起来您在循环的第一次迭代中,在各种可能的条件下调用了
cancel()
,那么为什么要执行循环呢?无论如何,您的
verifyLogin()
方法只是在另一个线程中启动验证过程,然后立即退出。
isValid
标志在该线程完成之前不会更改,这会在以后发生很多次。如果您想执行验证过程,然后再执行其他操作,那么在
verif中管理线程是没有意义的yLogin()
。这确实有效,但我之前确实做到了这一点,没有使用线程。我开始使用它的原因是因为我想获得“等待效果”。有几种情况,例如查询数据库或打开连接,程序会暂时冻结。我想我只需添加“动画”状态之后是点,所以一旦用户单击某个冻结程序的内容,他会看到当前状态,如“连接”。->“连接…”“->“连接…”等,而不是程序冻结。不知道如何使这些“点浮动”而程序正在等待一些data@user9309329如果不使用线程,进程运行时UI将完全无响应(其他控件无法工作,UI无法重新绘制,等等)。这里不是这样。例如,您可以在启动线程之前立即启动动画或显示进度指示器,并在
onSucceeded
中停止/删除它。我以前没有线程的方法根本没有进度指示器,一旦我决定添加它们,我意识到我需要线程来实现这一点,但恩,我在这个领域有点迷茫,因为我以前从未使用过它们。因此,基本上,我需要在
verifyTask
之前启动另一个任务,按照我的意愿更新我的
statusLabel
,并在“verifyTask”完成后停止?@user9309329在其中添加动画代码。不需要使用线程来创建动画。同样,您可以ld只需使用进度指示器,而不是自己编写。
/**
  * @return An empty string if the login is valid, or an error message otherwise
  */

public static String verifyLogin(String username, String password) throws SQLException{
   isValid = false ;
   if(username.equals("") || password.equals("")) {
       return "Pola nie mogą być puste";
   } 
   query = "SELECT login, password FROM users WHERE login = ?";
   Query.execute(query, username);
   if(!Query.resultSet.next()) {
       return "Nie ma takiego użytkownika";
   } 

   String passwordValue = Query.resultSet.getString(2);
   if(!password.equals(passwordValue)) {
       return "Podane hasło jest błędne" ;
   } 


   isValid = true;
   return "" ;

}
private void login() {
    if( SqlConnection.isConnected()) {
        Task<String> verifyTask = new Task<String>() {
            @Override
            protected String call() throws SQLException {

                return Authorization.verifyLogin(loginInput.getText(), passwordInput.getText());
            }
        };

        // probably better to use a progress indicator or similar here, but:

        Animation animation = new Timeline(
            new KeyFrame(Duration.ZERO, e -> Status.get().set("Weryfikacja.")),
            new KeyFrame(Duration.millis(200), e -> Status.get().set("Weryfikacja..")),
            new KeyFrame(Duration.millis(400), e -> Status.get().set("Weryfikacja...")),
            new KeyFrame(Duration.millis(600)));
        animation.setCycleCount(Animation.INDEFINITE);


        verifyTask.setOnSucceeded(event -> {
            animation.stop();
            Status.get().set(verifyTask.getValue());
            if(Authorization.isValid()) { // or if (verifyTask.getValue().isEmpty()) 
                // go to next menu
            }
        });

        verifyTask.setOnFailed(event -> {
            animation.stop();
            verifyTask.getException().printStackTrace();
            Debug.log(verifyTask.getException().toString());
        }

        animation.play();
        new Thread(verifyTask()).start();
    }
}