уничтожение асинхронной задачи, когда doInBackground зависает на сокете TCP - PullRequest
0 голосов
/ 15 марта 2012

IPString У меня довольно простое действие, которое работает следующим образом: в onCreate я вызываю подключение AsyncTask TCP Socket к удаленному серверу через собственный порт, отправляю быструю команду ASCII на сервер и обрабатываю ответ через onPostExecute ().Прекрасно работает, это быстро и функционально.

Однако, если удаленный сервер не работает - или я ошибочно ввел неправильный IP-адрес для связи - мой AsyncTask будет зависать при вращении диалога «вход в систему»на экране столько времени, сколько требуется для истечения времени ожидания сокета.

Последние два дня я копался в этом, пытаясь выяснить, как вызывать метод cancel (), но мне это не удается.Какие-либо предложения?Вот текущий код:

 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, чтобы отследить, сколько времени требуется, чтобы установить соединение (или нет), а затем каким-то образом «отменить ()» выполнение «try» внутри AsyncTask,но я терпел неудачу во многих стилях.

Это должно быть чем-то, что обычно используется, и должно быть простое решение?

ОБНОВЛЕНИЕ: Путь Iнаправлялся вниз, пытался использовать сокетное соединение из AsyncTask, чтобы «контролировать себя», и если / когда оно истекло, без получения надежного соединения - вызвать cancel () AsyncTask.Я пытался сделать это из самого AsyncTask, с помощью this.cancel () внутри перехвата IOException тайм-аута Socket.

До сих пор решение заключается в реализации таймера вне AsyncTask, который запускается нато же самое время, что и AsyncTask, и вызвать отмена после того, как прошло много секунд.Это решение изящно завершает попытку подключения, и я могу поместить любые триггеры Dialog или тосты в раздел onCancelled () AsyncTask.Он больше не падает, НО: сокет все еще пытается подключиться в фоновом режиме, даже если задача отменяется.

Ответы [ 2 ]

0 голосов
/ 15 марта 2012

Что именно вы пытаетесь сделать? Определить, когда вы ввели неправильный IP-адрес или сервер не работает? Показывать вход только определенное время? Я понял, что вы спрашиваете, как отменить асинхронную задачу, но это не является корнем проблемы, которую вы пытаетесь решить.

Я думаю, что MisterSquonnk совершенно прав, вы должны просто установить время ожидания при соединении с вызовом. В вашем коде может быть что-то еще, если этот тайм-аут не работает. В качестве альтернативы, если вы просто хотите что-то, что позволит вам сделать свой тайм-аут, не имея ничего общего с сокетом, см. Ниже:

Если вы хотите предположить, что ваше соединение не удалось за более короткий промежуток времени, чем время ожидания сокета, запустите новый CountDownTimer http://developer.android.com/reference/android/os/CountDownTimer.html в то же время и в том же месте в вашей активности когда вы запускаете асинхронную задачу с любой продолжительностью тайм-аута.

После того, как таймер закончится (и onFinish в таймере вызывается), вызовите отмену асинхронной задачи или иным образом запретите выполнение onPostExecute и сделайте все, что захотите, если попытка входа в систему не удалась в вашем пользовательском интерфейсе. Точно так же, если попытка входа в систему будет успешной до того, как таймер закончится, отмените таймер или иным образом предотвратите вызов onFinish.

0 голосов
/ 15 марта 2012

Определенно кажется, что самое простое решение (которое вы пробовали) - установить время ожидания при вызове connect.Можно ли опубликовать трассировку стека, сгенерированную при сбое соединения с тайм-аутом?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...