【问题标题】:Force stop a blocking read AsyncTask强制停止阻塞读取 AsyncTask
【发布时间】:2015-09-09 10:48:31
【问题描述】:

我的应用程序中有一个 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;
        }
        ...
    }

当我关闭我的应用程序时,我想停止 AsyncTask task:(按返回按​​钮)。 我在这里尝试了Android - Cancel AsyncTask Forcefully的答案以检查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);
    }

但是当调用task.cancle(true) 时,应用程序似乎会在myInputstream.read(readbyte) 处阻塞。 Android 会弹出一个“应用程序停止响应..”给我。 如何强制停止阻塞读取?

【问题讨论】:

  • 您是否在 doInBackground 中发现任何异常?应该有一个 InterruptedException。
  • @Fildor 它应该是java.io.InterruptedIOException,但前提是流支持中断。
  • 您说“应用程序似乎将在 myInputstream.read(readbyte) 处阻塞”。你有多大把握确实是这样?
  • 因为行间用了很多Log.d()打印,所以停在read(readbyte)
  • mySocket.connect(new InetSocketAddress(MYIP, MYPORT));。你不能在 onCreate 中这样做。使用 AsyncTask 的整个想法是将这样的“互联网代码”放在 AsyncTask 的 doInBackground 中。

标签: java android sockets android-asynctask


【解决方案1】:

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

myInputstream.read(readbyte)

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

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

中创建的Socket
mySocket = new Socket();

行。

mySocket.close();

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

关闭此套接字。

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

所以你的任务步将被解除阻塞,但你必须在你的任务中正确处理 SocketException 以终止所有操作(也许这就是你所缺少的)。

仅供参考

task.cancel(true);

没有多大意义,因为这只会在任务上设置cancelled 标志。检查标志是您的代码的责任,并且由于阻塞 I/O,您不可能这样做。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-21
    • 2020-04-03
    • 1970-01-01
    相关资源
    最近更新 更多