Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force stop a blocking read AsyncTask

I have an AsyncTask in my application:

public class myActivity extends Activity {
    private static Socket mySocket;
    private static InputStream myInputstream;
    private AsyncTask task;
    private boolean connected = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...            
        task = new UpdateTask().execute();
        ...
    }

    private class myTask extends AsyncTask<Void, String, String> {
        @Override
        protected String doInBackground(Void... v) {
            if(!connected) {
                try {
                    mySocket = new Socket();
                    mySocket.connect(new InetSocketAddress(MYIP, MYPORT));
                    myInputstream = mySocket.getInputStream();
                    connected = true;
                } catch(IOException e) { ... }
            }

            while(connected && !isCancelled()) {
                byte[] readbyte = new byte[1024];
                try {
                    myInputstream.read(readbyte);
                } catch (IOException e) { ... }
                ...
            }
            return null;
        }
        ...
    }

And I want to stop AsyncTask task when I close my application: (press back putton). I tried the answer here Android - Cancel AsyncTask Forcefully to check isCancelled()

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_BACK) {
            task.cancel(true);
            mySocket.close();
            finish();
        }
        return super.onKeyDown(keyCode, event);
    }

But it seems that application will block at myInputstream.read(readbyte) when task.cancle(true) is called. Android will throw an "app is stop responding.." pop-up to me. How can I force stop the blocking read?

like image 653
Dia Avatar asked Sep 09 '15 10:09

Dia


1 Answers

java.io.InputStream implements blocking I/O. It is expected that your application will block on

myInputstream.read(readbyte)

until the read operation will return -1 which means that there no more data to read from stream (as it was closed or connection was terminated) or throw the exception.

The only way to unblock the thread waiting for data on stream is to close it. In your case you need to be able to close the Socket created in

mySocket = new Socket();

line.

mySocket.close();

should interrupt your reading. But stay aware that Socket.close() actually

Closes this socket.

Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.

So you task tread will get unblocked but you have to handle the SocketException correctly in your task to terminate all operations (maybe this is what you are missing).

FYI calling the

task.cancel(true);

doesn't make much sense as this only sets the cancelled flag on task. It is responsibility of your code to check for the flag and with blocking I/O you have no possibility to do it.

Alternatively you should consider using non-blocking I/O.

like image 144
Aleh Maksimovich Avatar answered Oct 05 '22 23:10

Aleh Maksimovich