【问题标题】:Android: Warning when cancelling AsyncTask from doInBackgroundAndroid:从 doInBackground 取消 AsyncTask 时发出警告
【发布时间】:2012-02-18 04:25:48
【问题描述】:

我遇到了这个问题:

我有一个主 Activity 请求另一个类的信息,该类从 Web 服务获取该信息,所以我在 AsyncTask 类上执行此操作。在加载数据时,主 Activity 显示一个 ProgressDialog,我正在处理后退按钮,因此当按下它时我可以关闭对话框,但现在我想取消 AsyncTask。我创建了一个静态布尔变量,当按下后退按钮时它是“真”,所以从 AsyncTaskdoInBackground 方法我检查该变量是否为真,如果它是true 我取消了 AsyncTask

@Override protected Void doInBackground(Integer... args) {      
  try {
        ....        
      if ( MainActivity.isDialogCancelled ){
        cancel(true);
        }
        ....
  } catch (Exception e) {
      ....
  } 
}

这似乎工作正常,但是当我以这种方式取消任务时,我看到 InterruptedException 警告,为什么会发生这种情况以及如何避免它们?我做错了什么?

这些是警告:

01-24 18:40:50.582: W/AsyncTask(22877): java.lang.InterruptedException
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1272)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:220)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.FutureTask.get(FutureTask.java:83)
01-24 18:40:50.582: W/AsyncTask(22877):     at android.os.AsyncTask$3.done(AsyncTask.java:196)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.FutureTask$Sync.innerCancel(FutureTask.java:294)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.FutureTask.cancel(FutureTask.java:76)
01-24 18:40:50.582: W/AsyncTask(22877):     at android.os.AsyncTask.cancel(AsyncTask.java:325)
01-24 18:40:50.582: W/AsyncTask(22877):     at android.os.AsyncTask$2.call(AsyncTask.java:185)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.FutureTask.run(FutureTask.java:138)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
01-24 18:40:50.582: W/AsyncTask(22877):     at java.lang.Thread.run(Thread.java:1019)

提前致谢

【问题讨论】:

  • 你确定你是在正确的地方做的吗?你读过这个吗?取消任务- 可以通过调用 cancel(boolean) 随时取消任务。调用此方法将导致对 isCancelled() 的后续调用返回 true。调用此方法后,将在 doInBackground(Object[]) 返回后调用 onCancelled(Object),而不是 onPostExecute(Object)。为了确保尽快取消任务,如果可能(例如在循环内),您应该始终从 doInBackground(Object[]) 定期检查 isCancelled() 的返回值。
  • 对不起,我没有把整个代码,但我已经抓住了它,但它仍然在 Logcat 上显示警告,我更新了主帖子上显示 try/catch 的代码使用
  • 请不要对代码或堆栈跟踪使用引号样式,而是使用代码按钮(或行首的 4 个空格)。谢谢
  • @Sergey,我看了你贴的那段话,上面说我不能随时取消任务...我可以从类本身的方法 doInBackground 中取消任务吗?

标签: android


【解决方案1】:

为什么不使用 onPause() 中的asyncTask.cancel(true);??

【讨论】:

  • 因为有时您想使用安卓设备的取消按钮或后退按钮取消下载或任何长期任务。
  • 对,当我按下后退按钮时尝试取消任务时会发生此问题
【解决方案2】:

与任何其他 Thread 一样,您必须使用 try/catch 将其包装起来并捕获 InterruptedException

此外,AsyncTask 有一个函数cancel(boolean),用它代替你所做的,并使用isCacneled() 检查它是否被取消

【讨论】:

    【解决方案3】:

    我相信这里的其他答案是正确的,但只是为了尝试更彻底地解释一下:

    从您的AsyncTask 回调您的Activity 的方法以检查您是否应该取消是一个好习惯。

    正确方法(根据documentation):

    可以通过调用cancel(boolean) 随时取消任务。调用此方法将导致对isCancelled() 的后续调用返回true。调用此方法后,onCancelled(Object) 将在 doInBackground(Object[]) 返回后调用,而不是 onPostExecute(Object)为确保尽快取消任务,您应始终定期从doInBackground(Object[]) 检查isCancelled() 的返回值,如果可能的话(例如在循环内)。

    (粗体字)

    因此,您的代码中有正确的基本概念,但不是在您的 Activity 上设置某些内容,而是在您想取消它时调用 AsyncTask 的 cancel() 方法。这会更改isCancelled() 方法的返回值。然后,在您的 doInBackground() 方法中,您应该检查 isCancelled() 值并根据结果选择您的行为。

    是的,虽然它可能并不理想,但我已经看到从 doInBackground() 方法内部调用 cancel(true); 的功能代码。

    【讨论】:

      【解决方案4】:

      Cancel(false) 只是设置 asynctask 的取消标志。如果您调用 cancel(true),它会设置 asynctask 的取消标志并中断运行 asynctask 的后台线程。这就是interruptedException的来源。

      【讨论】:

        猜你喜欢
        • 2011-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多