AsyncTask: doInBackground未被调用

11

我在使用AsyncTask时遇到了问题。有时doInBackground()方法不会在onPreExecute()方法之后被调用。

我知道这个问题已经被问过几次,但是给出的答案对我无效。

以下是我的部分代码:

AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>(){

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        Log.e("AsyncTask", "onPreExecute");
    }

    @Override
    protected Void doInBackground(Void... params) {
        Log.e("AsyncTask", "doInBackground");
        return null;
    }

    protected void onPostExecute(Void result) {
        Log.e("AsyncTask", "onPostExecute");
    };

};

if(Build.VERSION.SDK_INT >= 11)
    asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
    asyncTask.execute();

正如你所看到的,我检查Android版本是否>= HoneyComb,并在它为真时在池执行器中执行任务。尽管有这个“技巧”,有时仍然不会调用doInBackground()

有人遇到相同的问题或知道问题出在哪里吗?

谢谢


1
有时候我会遇到这个问题,如果已经有一个AsyncTask在运行,那么是否可能呢? - Cornholio
发布完整的代码。它可以用于许多事情。 - njzk2
Cornholio: 是的,这是真的。其他AsyncTasks正在运行。(我明确指出它们是AsyncTasks的其他实例,而不是多次执行的相同实例) - Valentin
你尝试过重写onCancelled()方法,看看是否会出现任何错误吗?http://developer.android.com/reference/android/os/AsyncTask.html#onCancelled(Result) - Jonas Schmid
3个回答

38

最终我找到了解决问题的方法。

我实例化了自己的ThreadPoolExecutor,而不是使用*AsyncTask.THREAD_POOL_EXECUTOR*来执行asyncTask,设置了较大的corePoolSize和maximumPoolSize:

int corePoolSize = 60;
int maximumPoolSize = 80;
int keepAliveTime = 10;

BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(maximumPoolSize);
Executor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue);

而且...

asyncTask.executeOnExecutor(threadPoolExecutor);

我不知道这是否是一个好的Bug修复方法,但通过这种方式,doInBackground()将始终被调用。 正如你所说,我认为问题是*AsyncTask.THREAD_POOL_EXECUTOR*无法管理我分配给它的那么多个异步任务。

谢谢大家


请注意,此解决方案无法在2.3.X设备上使用,您将不得不使用“asyncTask.execute();”。 - Charlie-Blake
有人解决了2.3.X的问题吗?对于其他高于该版本的版本,它完美地运行。 - Bhupinder
@Valentin,非常好的解决方案! - Hiren Patel

2

这种情况曾经发生在我身上,因为我的一些任务在doInBackground()中被阻塞了(根据您提供的代码示例,显然是不可能出现这种情况的)。

据我上次检查时,Android的THREAD_POOL_EXECUTOR默认的线程池大小为5。因此,如果您同时执行超过5个任务,则下一个任务将等待直到前面的任务完成。

这是我所知道的唯一防止doInBackground()调用的情况。


Android上THREAD_POOL_EXECUTOR的默认池大小在我上次检查时为5。因此,如果您同时执行超过5个任务,则下一个任务将等待直到有任务完成。这很有趣。如果THREAD_POOL_EXECUTOR中已经有5个任务,并且我添加第六个任务,那么它的行为会是什么?1)第六个任务将永远不会执行doInBackground() 或 2)第六个任务将等待另一个任务完成后再执行 - Valentin
当一个任务完成后,第六个任务将开始。我希望只有现在才会调用onPreExecute,但从未真正检查过。 - Pedro Loureiro
1
@Valentin 是的,第六个任务已经排队了。请注意,如果您确实需要同时运行超过5个任务,可以使用更大的“CORE_SIZE”实例化自己的执行器。 - FabiF

0

你的代码看起来不错。

你只能运行一次异步任务。我猜测你正在尝试运行它们多次。

创建另一个实例然后再尝试。

如果还是不行,检查logcat并在此处发帖以获取足够的修复帮助。


这个 AsyncTask 实例只会被执行一次 :/ 但是,其他 AsyncTask 实例正在运行。我可以给 THREAD_POOL_EXECUTOR 分配的 AsyncTask 数量有上限吗? - Valentin
请检查logcat是否有任何错误。您可以提交任意数量的任务,没有限制。 - Pedro Loureiro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接