Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What can cause a AsyncTask not to execute?

I have a very sporadic failure in my app I'm trying to resolve. On entry to the app, at one point the main UI thread processing ends and passes control to a background thread to retrieve some data. When the data is retrieved, control passes back to the main UI thread to process it for display. However, on some rare occassions (it works 99% of the time), the AsyncTask seems to be failing to be called leaving the app in a poor static state forever waiting for the AsyncTask to complete.

Here's a snapshot of the code in the Activity:

//method call from main UI thread
private void fetchSomeData() {
    Log.d("myTag", "In fecthSomeData()");
    new ReadFileAsyncTask<DataModel>().execute(this);
}

Here's the ReadFileAsyncTask implementation:

public class ReadFileAsyncTask<A> extends AsyncTask<I_ReadFileListener<A>, Void, A>
{
I_ReadFileListener<A> listener;

@Override
@SuppressWarnings("unchecked")
protected A doInBackground(I_ReadFileListener<A>... params)
{
    listener = params[0];
    Log.d("mytag", "BACKGROUND: Loading " + listener.getFilename() + " from disk");
    A fileContents = (A) FileUtils.readDataFromInternalStorage(listener.getContext(), listener.getFilename());
    return fileContents;
}

@Override
protected void onPostExecute(A result)
{
    Log.d("myTag", "FOREGROUND: Executing onFileRetrieved listener");
    listener.onFileRetrieved(result);
}
}

Capturing the logs on this rare failure yeilds:

In fetchSomeData()
...
(Other log messages from other interactions with the activity such as menu creation and navigation initialization)

but, crucially, not the log statement from the second line of code in the doInBackground method. One thought I had was that this log statement was failing, but I'm not seeing any force stop messages, error in my logs or ACRA crash reports. The application is still active (I can navigate to other activities and back) so I'm at a loss as to what might stop this background thread from running properly. Any ideas?

like image 807
Chris Knight Avatar asked Nov 04 '22 04:11

Chris Knight


1 Answers

Sadly AsyncTask is not suitable for critical code execution since, depending on the ThreadPool base and max size, your AsyncTask may never execute.

Moreover, the onPostExecute method could be called when the Activity it is referring (i.e. its creating context) has already been destroyed. You have no way to synchronize with it rather then maybe using join() on the AsyncThread from the UI Thread.

Even though I've seen doing this also in the Android Camera App it isn't a good idea to block the UI Thread waiting for an event since you coulg get an ANR (Application Not Running) notification.

Take a look at this: Is AsyncTask really conceptually flawed or am I just missing something?

Consider using IntentServices, HandlerThread or ThreadPoolExecutors if you need a possibly better way to synchronize your worker thread with your your UIThread.

From http://developer.android.com/training/run-background-service/create-service.html:

Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask

like image 152
type-a1pha Avatar answered Nov 10 '22 17:11

type-a1pha