JavaFX为什么Task返回Null?

时间:2017-10-02 13:45:00

标签: javafx

我现在正在尝试学习线程和任务......但仍然无法在我的应用中实现它...帮助PLZ。

我想在除应用程序线程之外的后台线程中运行所有数据库操作。 我有一个管理数据库查询的类......在这个类中,我用一个任务包围了executeQuery语句:

public class Database {

ResultSet rs;

public ResultSet execQuery(PreparedStatement stmnt) throws SQLException {       
    Task<ResultSet> task = new Task<ResultSet>() {
     @Override protected ResultSet call() throws Exception {
             if (isCancelled()) {
             }                    

                 ResultSet execRs = stmnt.executeQuery();
                 return execRs;
         }
     };     
    task.run();
    task.setOnSucceeded(new EventHandler<WorkerStateEvent>(){
        @Override
        public void handle(WorkerStateEvent event) {                
             rs = task.getValue();
        }            
    });
    return rs;
}
// remaining Code
}

正如您所看到的,该方法应该返回一个ResultSet,但是当我从另一个地方调用它时,它会引发一个空指针...此方法返回的结果集为null。

那我在这里做错了什么?

更新#1 @James_D谢谢你这个伟大的link ...我想我终于理解了这个概念......但是实现它仍然存在一个小问题...例如在用户认证后我的身份验证方法中我想要检查该用户是否有开放班次...所以在你的链接后我改变了方法:

    private boolean isShiftOpen(int userId, int branchId, int comId) throws SQLException, ClassNotFoundException {
//        final boolean success = false; 
        Task<Shift> task = new Task<Shift>(){
            @Override
            protected Shift call() throws Exception {
                return ShiftDAO.getShift(userId, branchId, comId);
            }            
        };
        task.setOnFailed(e -> {
            System.out.println("isShiftOpenTask Faild!!");
            success = false;
        });
        task.setOnSucceeded(e -> {
            System.out.println("isShiftOpenTask Succeeded!!");
            Shift shift1 = task.getValue();
            System.out.println("User Open Shift Exists ... returning true");
            SessionBean.setShiftId(shift1.getShiftId());
            SessionBean.setUserId(shift1.getUserId());
            SessionBean.setUserBranch(branchId);
            success = true;
        });
        exec.execute(task);
        return success;

    }

我有两个问题: 1- exec.execute(任务)引发一个nullpoint异常。 2-我想使用这个方法返回的布尔变量...我可以访问这个变量的唯一方法是在方法之外定义...但是如果我想使用像这样的另一个方法我必须声明它的另一个布尔变量...这听起来对你好吗?

感谢您的时间 加多

1 个答案:

答案 0 :(得分:2)

你打电话

task.run();

执行当前线程上的任务,即该任务完成前该语句不会完成。 然后你打电话

task.setOnSucceeded(...);

基本上说“当任务成功时,将实例变量rs设置为任务的结果。但是,当你调用它时,任务已经成功(或可能失败),所以无法调用处理程序。

您可以通过颠倒这些调用的顺序来修复null结果,即执行

public ResultSet execQuery(PreparedStatement stmnt) throws SQLException {       
    Task<ResultSet> task = new Task<ResultSet>() {
     @Override protected ResultSet call() throws Exception {
             if (isCancelled()) {
             }                    

                 ResultSet execRs = stmnt.executeQuery();
                 return execRs;
         }
     };     
    task.setOnSucceeded(new EventHandler<WorkerStateEvent>(){
        @Override
        public void handle(WorkerStateEvent event) {                
             rs = task.getValue();
        }            
    });
    task.run();
    return rs;
}

但是,由于您正在当前线程上执行任务,因此根本不清楚使用任务的重点是:您也可以直接在execQuery方法中执行数据库查询,直接返回结果。换句话说,上面的代码相当于

public ResultSet execQuery(PreparedStatement stmnt) throws SQLException {       

     rs = stmnt.executeQuery();
     return rs;

}