【问题标题】:Is canceling an asyncTask expensive?取消 asyncTask 成本高吗?
【发布时间】:2014-05-10 05:35:27
【问题描述】:

因此,如果我有 5 个异步任务正在运行并且我取消它们,那么 UI 会冻结一点,但是如果我执行 20 个异步任务并取消它们,那么我的 UI 会冻结一段时间。我的问题是, asyncTask.cancel(true) 方法是否昂贵?我的用户界面是这样冻结的吗?我注意到当我不调用取消时,我的 UI 不会冻结。无论如何我可以防止我的用户界面冻结吗?我尝试将 .cancel(true) 方法放在它自己的线程中,但这没有帮助。

这里有一些代码。

     //could be as little as 1 or could be 20
    for( AsyncTask asyncTask : asyncTasks )
    {
        if ( asyncTask != null )
        {
            //seems to block UI for a bit if there are a lot of calls
            asyncTask.cancel( true );
        }
    }

【问题讨论】:

  • 你的任务的 onCancelled() 回调中有代码吗?
  • 是的,但如果我注释掉回调并运行应用程序,我似乎会这样做。同样的延迟也会发生。

标签: java android multithreading android-asynctask


【解决方案1】:

您的任务是否检查了doInBackground() 函数中的isCancelled()

AsyncTask 的目的是在后台快速运行(即计算时间短的任务)并将结果发布到 UI 线程。这意味着当您调用asyncTask.cancel(true); 时,不是在UI 线程上调用 onPostExecute,而是在UI 线程上调用onCancelled

由于在 UI 线程上调用了“取消”,如果您的线程处于紧密循环中并且不对任何全局变量或取消请求进行任何检查(例如检查 isCancelled),则可能需要一个 '底层 API 清理您的线程(正确结束/取消它而您的线程不会自行结束)的一点时间,“一点时间”就是您体验到的 UI 的“暂停”。

为了缓解这种情况,在您的 doInBackground 函数中,只需检查 isCancelled 函数:

// simple example function:
protected Void doInBackground (Void... params) {
    for(int i=0; i < 65535; ++i) {
        if (isCancelled()) { break; } // exit loop on cancel request
    }
    return null;
}

在这个AsyncTask 中,如果我们随后调用asyncTask.cancel(true);,循环将在下一次检查isCancelled 时中断,UI 线程可以继续而不是等待循环完成它的迭代(因此“暂停” UI 直到线程完成)。

希望能有所帮助。

【讨论】:

    【解决方案2】:

    在进行取消调用后,我正在记录使用 jackson 库的对象。它重新实例化了

    ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); 
    

    每次我都想用这个方法。因此,我只是实例化了 new ObjectMapper().writer().withDefaultPrettyPrinter();一次,它解决了我在 UI 上的延迟问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多