一般情况下,我有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)
谢谢!
答案 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)上串行执行,因此长时间运行的工作程序可以阻止其他人;