简体   繁体   English

服务内的线程-需要等待线程完成[Android]

[英]Thread inside Service - Need to wait until Thread is finished [Android]

I have my application connecting to a server over SSH (Using JSch) but the app cant keep up if I send commands without waiting for the result to come back and it misses the reply as the next command gets sent without waiting. 我的应用程序通过SSH(使用JSch)连接到服务器,但是如果我发送命令而没有等待结果返回,该应用程序将无法跟上,并且由于下一条命令没有等待发送而错过了答复。

I have tried a few methods eg using an Object to synchronize the Thread and using wait() and notify() but the UI thread stays frozen doing this. 我尝试了一些方法,例如使用对象同步线程,并使用wait()和notify(),但是UI线程在执行此操作时保持冻结状态。 And thread.join() which worked but resulted in it running very slowly as it froze between commands. 和thread.join()起作用,但由于在命令之间冻结而导致运行非常缓慢。

Long story short, I need to wait for a reply from the server, process it and plot it, then send the next command. 长话短说,我需要等待服务器的回复,对其进行处理和绘制,然后发送下一条命令。

Any help is greatly appreciated as this is for my Computing project. 非常感谢您的帮助,因为这对我的计算机项目是有帮助的。 :D :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 eg 37.5 // UI Freezes here 

I have read that I could use an AsyncTask here instead of a thread... Not sure if I can do that inside of a Service though... :P 我读过我可以在这里使用AsyncTask而不是线程...不确定我是否可以在Service内执行此操作...:P

See #sending-commands-to-server-via-jsch-shell-channel 请参阅通过jsch-shell-channel向服务器发送命令

... if you are not sure how many lines to read and thus want to use "while", make sure you do something inside while to prevent 1) busy-waiting 2) ending-condition. ...如果不确定要读取多少行并因此想使用“ while”,请确保在while内执行一些操作,以防止1)忙等待2)结束条件。 Example: 例:

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

To process your in-out from the other Thread , you may use #non-blocking-buffer 要处理其他线程的出入,可以使用#non-blocking-buffer

Take a look over the jsch examples . 看一下jsch示例

Also, as design suggestion, you may use UserInfo interface for passing your credentials, and not directly from your UI objects. 另外,作为设计建议,您可以使用UserInfo接口来传递您的凭据,而不是直接从UI对象中传递。

A similar project with yours (web based, not android): https://github.com/kohsuke/ajaxterm4j 与您的类似项目(基于Web,不是android): https : //github.com/kohsuke/ajaxterm4j

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM