我有一个AsyncTask,我在Activity的onPause生命周期事件中关闭,因此当有人离开应用程序时它不会运行,但它会继续运行,尽管如此。我添加了一些跟踪,这个片段显示了问题。
Trace.d(TAG,"Task state: " + myTask.getStatus() );
myTask.cancel(true);
Trace.d(TAG,"Task state: " + myTask.getStatus() );
输出:
Task state: RUNNING
Task state: RUNNING
为什么cancel()方法对任务的状态没有任何影响?我注意到文档说取消方法将“尝试”停止任务,但在什么情况下会失败?该任务肯定在运行,因为它每十秒输出一次日志输出,正如您在上面所看到的,它的状态将返回为运行状态。
更新:我添加了跟踪以显示isCancelled()状态,并且会更改。所以取消(true)的调用是将取消状态从false更改为true,但显然对Status没有影响,或者停止线程。
答案 0 :(得分:3)
请记住,您的Activity和AsyncTask是两个独立的线程。因此,即使取消AsyncTask,取消任务的代码也可能无法运行!这就是为什么即使在修复bug之后你仍然看到AsyncTask仍在运行的原因。在AsyncTask完成doInBackground()
之前,我认为状态不会改变。 (因此,请确保您正在检查isCancelled()
并在取消时提前返回!)
答案 1 :(得分:2)
我深入挖掘并记得我的线程正在调用一个写得很糟糕的方法,在我需要取消的那个内部生成另一个线程:
public static void haveASleep(int milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException ie)
{
Trace.w(TAG,"Sleep interrupted");
}
}
所以发生的事情是AsyncTask线程调用此方法等待一段时间,并且在睡眠期间,在AsyncTask上发生cancel()方法调用,这会导致线程休眠中出现异常。我的代码无益地捕获并吸收了该异常,而不是使用它来关闭AsyncTask。
解决方案是在睡眠中寻找异常,如果抛出异常,则静静地退出线程。该应用现在按预期工作,但是......
cancel()方法调用之后的状态仍然是RUNNING,但我怀疑这是因为此时它仍在运行,并且操作系统尚未将其关闭。我不知道这是否属实,但那是我最好的估计。
答案 2 :(得分:2)
thread.cancel(true);
仅在AsyncTask类中设置变量。你需要做的是在你的后台任务中实现一个循环,如果你还没有。如果每次迭代取消为真,则检查并中断循环。
@Override
protected Void doInBackground(Void... params) {
synchronized(this) {
for(int i = 0; i < 9000; i++) {
if(thread.isCancelled()) break;
// do stuff
}
}
}
然后只需在需要停止时将其设置为取消。然后它将在下一次迭代之前停止。
@Override
public void onStop() {
super.onStop();
thread.cancel(true);
}
@Override
public void onDestroy() {
super.onDestroy();
thread.cancel(true);
}
答案 3 :(得分:0)
即使您知道取消是如何工作的,也很难确定您的线程将在什么状态下停止。所以我建议你实现自己的安全方法来阻止你的线程,这样你就可以确定你停止了什么状态,你确定没有内存泄漏等等。从更多信息如何在java中停止一个线程安全检查此帖子How to abort a thread in a fast and clean way in java?
答案 4 :(得分:0)
检查您是否遇到此问题的另一个可能的陷阱:
确保您没有启动两个AsyncTasks。