当doInBackground挂在TCP套接字杀害的AsyncTask [英] killing asynctask when doInBackground hangs on a TCP Socket

查看:99
本文介绍了当doInBackground挂在TCP套接字杀害的AsyncTask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

IPStringI有一个相当简单的活动,工​​作过程如下:
在OnCreate,我叫了一个专有的端口的TCP AsyncTask的Socket连接到远程服务器,发送快速ASCII命令到服务器并处理经由onPostExecute响应()。伟大的作品,它的快速和功能。

IPStringI have a fairly simple Activity which works as follows: in the onCreate, I call an AsyncTask TCP Socket connection to a remote server over a proprietary port, send a quick ASCII command to the server and process the response via the onPostExecute(). Works great, it's fast and functional.

但是,如果远程服务器停机 - 或者我误在错误的IP地址的通信进入了 - 我的AsyncTask将与挂起登录对话框中纺在屏​​幕上,只要它需要的套接字超时。

However, if the remote server is down -- or I mistakenly entered in the wrong IP address for the communication -- my AsyncTask will hang with the "logging in" dialog spinning on the screen for as long as it takes for the Socket to timeout.

我已经挖走这对最后2天,试图找出如何调用cancel(),但我失败了。有什么建议么?
下面是目前的code:

I've been digging away at this for the last 2 days trying to figure out how to call the cancel(), but am failing. Any suggestions? Here's the current code:

 public class Scratchpad extends AsyncTask<Object, String, String>{
private String returningResponse;
private volatile Socket socket;

@Override 
protected void onPreExecute(){
    //throw the "Logging In" dialog up
    initializeDialog();     
    super.onPreExecute();
}
@Override
protected void onProgressUpdate(String... values) {
    super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String result) {
    //send the ASCII result off to the function that parses through it
    loginTriggerResult(result);
    super.onPostExecute(result);
}
@Override   
protected String doInBackground(Object... params) {
        /*
         * bunch of stuff goes here to strip out the proper 
         * values from the Object for IP address, Port number etc. 
         * params[0], params[1] etc.
         * 
        */
    InetAddress serverIP = null;
    String IPString = (String) params[1];
    int portnumber = (Integer) params[2];

    //convert the String "IPString" into an InetAddress
    try {
        serverIP = InetAddress.getByName(IPString);
    } catch (UnknownHostException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    //and then, bingo bango bongo, make the connection with the 'try':
    try{
        socket = new Socket(serverIP.getHostAddress(), portnumber);
        //I tried this too, forcing the timeout...  It crashes immediately.
        //SocketAddress socketAddress = new InetSocketAddress(serverIP.getHostAddress(), portnumber);
        //socket.connect(socketAddress, 3000);
        Log.d("networking","Connection Completed");

        //bunch of stuff goes here that happens AFTER the solid connection,
        //which we never get to if the Socket fails on a "waiting to connect" thing.

        //reader.close();
        //outputStream.close();

    }catch (SocketException e){
        e.printStackTrace();
        Log.w("socket","socket closed with SocketException");
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        Log.w("socket","socket closed with IOException");
    }       
    return returningResponse;   //postExecute will handle this.
}

}

我没有得到任何日志消息,直到3或4分钟过后,走出插座倍。
我想必须有某种方式运行的TimerTask或东西以外的的AsyncTask来跟踪它的服用多长时间进行连接(或没有),然后办法取消()运行'尝试'的AsyncTask的里面,但我一直没有在众多的风格。

I'm not getting any of the Log messages until the 3 or 4 minutes pass that the socket times out. I'm thinking there must be a way to run a TimerTask or something OUTSIDE of the AsyncTask to track how long it's taking to make the connection (or not) and then somehow "cancel()" the running 'try' inside the AsyncTask, but I've been failing on numerous styles.

这是东西是常用的,有一定有一个简单的解决方案?

This HAS to be something that's commonly used, and there's gotta be an easy solution?

更新:
我在标题下的路径试图使用套接字连接从内部的AsyncTask为自我监控,如果/当它超时没有得到坚实的连接 - 触发取消()中的AsyncTask的。
我试图从AsyncTask的本身做到这一点,与this.cancel()的套接字超时的IOException异常抓进去。

UPDATE: The path I was heading down was trying to use the socket connection from within AsyncTask to "monitor itself", and if/when it timed out without getting a solid connection -- trigger the cancel() of the AsyncTask. I was trying to do this from within the AsyncTask itself, with this.cancel() inside the IOException catch of the Socket timeout.

解决方案到目前为止是实现一个计时器启动,同时作为的AsyncTask的AsyncTask的外面,并要求从那里然而,许多秒钟后蒸发取消。
该解决方案确实优雅地退出连接尝试,我可以把任何形式的对话触发或的AsyncTask的onCancelled()里面节祝酒词。
它不会崩溃了,但是:插座仍试图在后台连接,即使任务被取消

The solution so far is to implement a timer outside of the AsyncTask that launches at the same time as the AsyncTask, and call the cancel from there after however many seconds have transpired. This solution does gracefully exit from the connection attempt, and I can put any sort of Dialog triggers or Toasts inside the onCancelled() stanza of the AsyncTask. It doesn't crash anymore, BUT: the socket is still trying to connect in the background, even though the task is cancelled.

推荐答案

究竟它是你想做些什么?检测当你输入了错误的IP地址或服务器已关闭?只显示登录了一定的时间?我得到你问如何取消异步任务,但似乎并没有被你试图解决的问题的根源。

What exactly is it are you trying to do? Detect when you've entered the wrong IP address or the server is down? Only show logging in for a certain amount of time? I get that you're asking how to cancel your async task, but that doesn't seem to be the root of the problem you're trying to solve.

我觉得MisterSquonnk是完全正确的,你就应该能够在通话连接设置超时时间。您可能有别的东西在你的code破碎如果超时不工作。或者,如果你只是想要的东西,可以让你做你自己的超时时间,而无需任何与插座,见下图:

I think MisterSquonnk is exactly right, you should just be able to set the timeout duration when call connect. You may have something else broken in your code if that timeout doesn't work. Alternatively if you just want something that lets you do your own timeout without having anything to do with socket, see below:

如果你想假设你正在连接失败在更短的时间量比插座需要超时,开始一个新的CountDownTimer的 http://developer.android.com/reference/android/os/CountDownTimer.html 在同一时间,在您的活动在同一个地方,你你想要的超时时间是什么启动异步任务。

If you want to assume you're connection has failed in a shorter amount of time than the socket takes to time out, start a new CountDownTimer http://developer.android.com/reference/android/os/CountDownTimer.html at the same time and in the same place in your activity as you start your async task with whatever you want the timeout duration to be.

在定时器运行后(而且onFinish在计时器被调用),调用从执行取消异步任务,否则prevent onPostExecute,做任何你想做的事当登录尝试在UI失败。同样的,如果计时器耗尽之前的登录尝试成功,取消计时器或prevent onFinish被调用。

After the timer runs out (and onFinish in the timer is called), call cancel on the async task, or otherwise prevent onPostExecute from executing, and do whatever you want to do when a login attempt fails in your UI. Similarly if the login attempt succeeds before the timer runs out, cancel the timer or otherwise prevent onFinish from being called.

这篇关于当doInBackground挂在TCP套接字杀害的AsyncTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆