强制停止阻塞读取AsyncTask

Dia*_*Dia 9 java sockets android android-asynctask

我的应用程序中有一个AsyncTask:

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;
        }
        ...
    }
Run Code Online (Sandbox Code Playgroud)

task当我关闭我的应用程序时,我想停止AsyncTask :(按回putton).我在这里尝试了Android的答案- 取消AsyncTask强力检查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);
    }
Run Code Online (Sandbox Code Playgroud)

但似乎应用程序将在调用myInputstream.read(readbyte)时阻塞task.cancle(true).Android将弹出一个"应用程序停止响应.."弹出窗口给我.我如何强制停止阻止读取?

小智 1

java.io.InputStream实现阻塞 I/O。预计您的应用程序将被阻止

myInputstream.read(readbyte)
Run Code Online (Sandbox Code Playgroud)

直到read操作返回-1,这意味着没有更多数据可以从流中读取(因为它已关闭或连接已终止)或抛出异常。

解除阻塞等待流数据的线程的唯一方法是关闭它。在您的情况下,您需要能够关闭Socket创建的

mySocket = new Socket();
Run Code Online (Sandbox Code Playgroud)

线。

mySocket.close();
Run Code Online (Sandbox Code Playgroud)

应该打断你的阅读。但请注意,Socket.close()实际上

关闭此套接字。

当前在此套接字上执行 I/O 操作时被阻塞的任何线程都将抛出 SocketException。

因此,您的任务步骤将被解锁,但您必须SocketException在任务中正确处理以终止所有操作(也许这就是您所缺少的)。

仅供参考,致电

task.cancel(true);
Run Code Online (Sandbox Code Playgroud)

没有多大意义,因为这只会cancelled在任务上设置标志。您的代码有责任检查该标志,而对于阻塞 I/O,您无法执行此操作。

或者,您应该考虑使用非阻塞 I/O。