服务中的线程 - 需要等到线程完成[Android]

时间:2015-02-12 00:39:11

标签: java android multithreading

我的应用程序通过SSH连接到服务器(使用JSch),但是如果我发送命令而不等待结果返回它并且它错过了回复,因为下一个命令在没有等待的情况下发送,应用程序无法跟上。 / p>

我尝试了一些方法,例如使用Object同步Thread并使用wait()和notify(),但UI线程保持冻结状态。而thread.join()虽然有效但导致它在命令之间冻结时运行速度非常慢。

长话短说,我需要等待服务器的回复,处理并绘制它,然后发送下一个命令。

非常感谢任何帮助,因为这是我的计算项目。 :d

    
//A snippet of my service procedure that handles the SSH connections

public String sendCommand(final String command) {
        Finished = false;
        final Thread sshServiceThread = new Thread(new Runnable() {
            String sshPassword = null;
            private volatile boolean running = true;

                @Override
                public void run () {
                    while (running) {
                        try {
                            session = jSch.getSession(username, host, port);
                            checkPassword();
                            session.setPassword(sshPassword);
                            session.setConfig("StrictHostKeyChecking", "no");
                            //TODO - REMOVE THIS
                            Log.w("DEBUG", "Host: " + host + " Username: " + username + " Password: " + password);
                            Log.w("Security", "REMOVE THIS BEFORE RELEASE");
                            session.connect();
                            channel = session.openChannel("shell");

                            DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream());

                            InputStream in = channel.getInputStream();

                            channel.connect();

                            //Send command
                            Log.w("Command", "Command: " + command);
                            dataOut.writeBytes(command + " && echo TheCommandWasFinished" + "\r\n");
                            dataOut.flush();

                            byte[] tmp = new byte[1024];
                            String replyLine = "";
                            try {
                                while (true) {
                                    while (in.available() > 0) {
                                        int i = in.read(tmp, 0, 1024);
                                        if (i < 0)
                                            break;
                                        String lastLine = replyLine;
                                        replyLine = (new String(tmp, 0, i));

                                        if (!replyLine.contains("&& echo TheCommandWasFinished")) {
                                            if (replyLine.contains("TheCommandWasFinished")) {
                                                String result = lastLine;
                                                Log.w("Result", result);
                                                reply = result;
                                                synchronized (syncObject) {
                                                    notify();
                                                }
                                                return;
                                            }
                                        }
                                    }
                                }
                            } catch (Exception exception) {
                                Log.w("Exception", exception);
                            }

                        } catch (JSchException jschX) {
                            Log.w("Exception", jschX);

                            if (jschX.toString().contains("timeout")) {
                                Log.w("Error", "IP Address is incorrect");
                                Toast.makeText(getApplicationContext(), "Cannot connect to host, Check IP and connection.", Toast.LENGTH_LONG).show();

                            }

                            if (jschX.toString().contains("Auth fail")) {
                                Log.w("Error", "Username/Password Incorrect");
                                Toast.makeText(getApplicationContext(), "Username/Password Incorrect", Toast.LENGTH_LONG).show();
                            }

                            if (jschX.toString().contains("ECONNRESET")) {
                                Toast.makeText(getApplicationContext(), "Connection failure", Toast.LENGTH_LONG).show();
                            }

                        } catch (IOException Exception) {
                            Log.w("Exception", Exception);
                        }
                    }
                }
            void checkPassword() {
                Log.w("Password set", "Password: " + sshService.password);
                sshPassword = sshService.password;
            }
        });
        sshServiceThread.start();

        try {
            synchronized(syncObject) {
                syncObject.wait(3000);
            }
        }
        catch (Exception Exception) {
            Log.w("Exception", Exception);
        }
        Finished = true;
        return reply;
    }

// Last few lines of my Logcat

02-12 00:11:10.281  32701-32701/com.lonedev.slypanel W/Values﹕ Host: 192.168.0.14 Username: adam
02-12 00:11:10.282  32701-32701/com.lonedev.slypanel W/Save﹕ Saved 192.168.0.14 adam
02-12 00:11:10.354  32701-32701/com.lonedev.slypanel W/Host:﹕ 192.168.0.14
02-12 00:11:10.355  32701-32701/com.lonedev.slypanel W/Host:﹕ 192.168.0.14
02-12 00:11:13.398    32701-684/com.lonedev.slypanel W/Password set﹕ Password: **********
02-12 00:11:13.399    32701-684/com.lonedev.slypanel W/DEBUG﹕ Host: 192.168.0.14 Username: adam Password: **********
02-12 00:11:13.399    32701-684/com.lonedev.slypanel W/Security﹕ REMOVE THIS BEFORE RELEASE
02-12 00:11:13.794    32701-684/com.lonedev.slypanel W/Command﹕ Command: top -b -n2 | grep "Cpu(s)" | awk '{print $2 + $4}' | tail -1

 // This should return a value for cpu usage e.g. 37.5
// UI Freezes here

我已经读过我可以在这里使用AsyncTask而不是线程...不确定我是否可以在服务中执行此操作,但是......:P

1 个答案:

答案 0 :(得分:0)

请参阅#sending-commands-to-server-via-jsch-shell-channel

  

...如果您不确定要阅读多少行并因此想要   使用“while”,确保你在内部做一些事情,以防止1)   忙碌的等待2)结束条件。例如:

while(!end)
{
   consoleOutput.mark(32);
   if (consoleOutput.read()==0x03) end = true;//End of Text
   else
   { 
     consoleOutput.reset();
     consoleOutput.readLine();
     end = false;
   }
}

要从其他主题处理您的输入内容,您可以使用#non-blocking-buffer

查看jsch examples

此外,作为设计建议,您可以使用UserInfo界面来传递您的凭据,而不是直接从您的UI对象。

与您的类似项目(基于网络,而不是Android):https://github.com/kohsuke/ajaxterm4j