3

I have a piece of code running the background using AsyncTask. The code is similar to this:

private class MyAsyncTask extends AsyncTask<Void, Void, Object> {

    public MyAsyncTask() {
        // Some init. code
    }

    @Override
    protected Object doInBackground(Void... params) {
        // Doing some long running task.
        Log.v(TAG, "Finished everything. Returning ...");
        return result;
    }

    @Override
    protected void onCancelled(Object result) {
        // Either way, run the next one in the line.
        Log.v(TAG, "Task cancelled");
    }

    @Override
    protected void onPostExecute(Object result) {
        Log.v(TAG, "Task Completed.");
    }

}

On Android 4 it works just fine, but when I run it on 2.3 (HTC Wildfire is my only test phone for now), onPostExecute is not called.

I can see the last message from doInBackground, but none of the messages from either onCancelled or onPostExecute. has anyone else faced the same issue? I found this link which talks about a similar problem, but neither gives a clear solution (just suggests using normal thread instead of AsyncTask) nor its precisely what I am looking for.

Any suggestions?

Cheers

Edit 1:

Ok, after spending a day and reading the code for AsyncTask, Handler, and Message in both 2.3 and 4, I have more clues now about what is happening.

First a little bit more about my design. I have a singleton class which is used both in the app and also in some services started from my app. So the AsyncTask code I showed above can be run either from the activity (assuming the singleton is accessed via the activity), or from the service (if the singleton is accessed via service).

Now in API 11+, no matter how the singleton is accessed, the onPostExecute is called just fine. On API 10 and below, if the singleton is accessed from the activity, then onPostExecute is called just fine, but if it's accessed via service, onPostExecute is not called.

Here is more details about where it get stuck. AsyncTask on 2.3 has an FutureTask which overrides done function to send a Message to its internal Handler as follow:

        mFuture = new FutureTask<Result>(mWorker) {
        @Override
        protected void done() {
            Message message;
            Result result = null;

            try {
                result = get();
            } catch (final InterruptedException e) {
                android.util.Log.w(AsyncTask.LOG_TAG, e);
            } catch (final ExecutionException e) {
                throw new RuntimeException("An error occured while executing doInBackground()",
                        e.getCause());
            } catch (final CancellationException e) {
                message = AsyncTask.sHandler.obtainMessage(AsyncTask.MESSAGE_POST_CANCEL,
                        new AsyncTaskResult<Result>(AsyncTask.this, (Result[]) null));
                message.sendToTarget();
                return;
            } catch (final Throwable t) {
                throw new RuntimeException("An error occured while executing "
                        + "doInBackground()", t);
            }

            message = AsyncTask.sHandler.obtainMessage(AsyncTask.MESSAGE_POST_RESULT, new AsyncTaskResult<Result>(AsyncTask.this, result));
            message.sendToTarget();
        }
    };

The last two lines of the following code calls message.sendToTarget which is supposed to call handleMessage of the Handler class, but it does not! now I have no idea why the callback to the handler happens from an activity and not from a service! I have some solutions how to solve this (simply using AsyncTask class for API15+ in my code at all times), but any explanation about the cause of this would be very much appreciated as I have no knowledge on this!

Thanks

Community
  • 1
  • 1
m.hashemian
  • 1,786
  • 2
  • 15
  • 31
  • can you show the code where the asynctask is being executed? is it being executed from another thread? – nandeesh Dec 16 '12 at 05:46
  • Does `doInBackground()` ever return? If it is blocked for some reason, `onPostExecute()` won't be called. Also try on different devices and/or the emulator to check whether this is device specific. `AsyncTask` most certainly works on 2.3. – Nikolay Elenkov Dec 17 '12 at 04:09
  • Yes, doInBackground does return. I updated my post with more detailed explanation which might be helpful. – m.hashemian Dec 18 '12 at 01:23
  • This statement is in the AsyncTask documentation: "When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution." They don't give an example of 'common application errors' but it is something that changed in the API after 2.3. – achoo5000 Jan 11 '14 at 22:34
  • possibly relevant: http://stackoverflow.com/a/7818839/697611 – achoo5000 Jan 11 '14 at 22:44
  • What did you end up doing, assuming that just not executing the Async task when below a certain API level is not OK.... – Andrew Mackenzie Mar 27 '14 at 08:08

1 Answers1

-2

official document is very detail,try to read it.

Kindly check this link it might help you

http://foo.jasonhudgins.com/2010/05/limitations-of-asynctask.html

OK~ notice:

onCancel function executes when you invoke cancel(boolean) method. have you called this function?

daimajia
  • 967
  • 12
  • 15
  • 2
    Please explain for benefit of others why, posting a link is not good enough :) – t0mm13b Dec 16 '12 at 03:31
  • try to retype or regenerate the @Override or using eclipse by clicking right mouse button->source-> Override\Implement method. – daimajia Dec 16 '12 at 05:17
  • -1 for both giving a simple link and for blatantly copying the other answer. This is *not* how StackOverflow works. – Cat Dec 16 '12 at 06:52
  • I am so sorry~ I am not familiar with this kind of comment system. I made a mistake, clicked other's post `edit` button. I want to tell m.hashemian if he/she could post the source... I want to try to help he/she as a kind redeeming of myself... – daimajia Dec 16 '12 at 07:37
  • Maybe my explanation was not very clear. I call `doInBackground` through `execute()` function, and expected to get a callback to either `onCancelled` or to `onPostExecute`, but none of them get called. This is the case only on 2.3 Wildfire (I have not tested it on emulator or other 2.3 phones). I know the documentation very well, and even I have gone through the source code, but still can't explain this behavior. Thanks for response anyways. – m.hashemian Dec 16 '12 at 20:16
  • could you email me part of your code (AsyncTask which not working in your emulator) Let me help you to test and try to modify. this is my email smallbeardict@163.com – daimajia Dec 16 '12 at 23:08