取消AsyncTask遇到了Thread.sleep

时间:2016-05-17 07:56:08

标签: android xamarin android-asynctask

一般情况下,我有AsyncTask我要取消它。在其doInBackground方法中,我有两种Thread.sleep方法,在它们之间我检查了AsyncTask#cancel是否使用isCancelled()调用。

以下是问题:如果Thread.sleep方法中有doInBackground,则AsyncTask#onCancelled()将不会被调用。如果删除了所有Thread.sleep,则会调用AsyncTask#onCancelled()是什么导致这种情况发生

这是演示的定义。

inner class DemoAsyncTask() : AsyncTask<String, Int, String>() {
    //        var isRunning = true
    override fun doInBackground(vararg params: String?): String? {
        Log.i(TAG, "##AsyncTask doing something...")

        var i = 0
        val TOTAL = 100000000
        var progress = 0
        while (i < TOTAL && !isCancelled) {
            Log.d(TAG, "doning jobs $i is cancelled $isCancelled")
            i++

            var currentProgress = i / TOTAL
            if (currentProgress > progress) {
                progress = currentProgress
                publishProgress(progress)
            }
        }

        Log.d(TAG, "doning jobs $i is cancelled $isCancelled")

        return "Task done"
    }

    override fun onPostExecute(result: String?) {
        this@CancalableActivity.mAsyncTextView?.text = result
    }

    override fun onProgressUpdate(vararg values: Int?) {
        mAsyncTextView?.text = "${mAsyncTextView?.text ?: "Async task..."} progress: ${values?.get(0) ?: 0}"
    }

    override fun onCancelled() {
        Log.i(TAG, "##Task cancelled")
//            isRunning = false
        this@CancalableActivity.mAsyncTextView?.text = "###Task cancelled"
    }
}

doInbackground可以正常工作,问题发生的原始版本如下:

if (isCancelled) {
    var msg = mHandler.obtainMessage(THREAD_CANCELLED)
    mHandler.sendMessage(msg)
    return
}

Thread.sleep(2000)

if (isCancelled) {
    var msg = mHandler.obtainMessage(THREAD_CANCELLED)
    mHandler.sendMessage(msg)
    return
}

var msg = mHandler.obtainMessage(THREAD_FINISHED)
mHandler.sendMessage(msg)

谢谢!

1 个答案:

答案 0 :(得分:0)

无法在纯java(api 23)中重现您的问题,这里是日志:

I/NSA: doInBackground 0
I/NSA: doInBackground 1
I/NSA: wait 2 sec and cancel
W/System.err: java.lang.InterruptedException
I/NSA: should be cancelled
W/art: Suspending all threads took: 15.850ms
W/System.err:     at java.lang.Thread.sleep(Native Method)
W/System.err:     at java.lang.Thread.sleep(Thread.java:1031)
W/System.err:     at java.lang.Thread.sleep(Thread.java:985)
W/System.err:     at org.dodroid.test_dialog.AsyncTaskX.doInBackground(AsyncTaskX.java:19)
W/System.err:     at org.dodroid.test_dialog.AsyncTaskX.doInBackground(AsyncTaskX.java:7)
W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:295)
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
W/System.err:     at java.lang.Thread.run(Thread.java:818)
I/NSA: doInBackground 2
D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
I/Adreno-EGL: <qeglDrvAPI_eglInitialize:379>: QUALCOMM Build: 10/21/15, 369a2ea, I96aee987eb
I/OpenGLRenderer: Initialized EGL, version 1.4
I/NSA: task was cancelled, sending message
I/NSA: handleMessage
I/NSA: onCancelled

你可以考虑另一种架构(看服务),因为有一些缺点:

  • AsyncTask只能用于需要几秒钟的任务;

  • AsyncTasks在单个后台线程(来自API 11)上串行执行,因此长时间运行的工作程序可以阻止其他人;