Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7656477
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T12:46:25+00:00 2026-05-31T12:46:25+00:00

I have an AsyncTask that fetches some data and then updates the UI with

  • 0

I have an AsyncTask that fetches some data and then updates the UI with this new data. It has been working fine for months, but I recently added a feature that displays a notification when there is new data. Now when my app is launched through the notification, sometimes I get this exception and onPostExecute is not called.

This is what happens when the app is launched:

1) Expand the UI and find views

2) Cancel the alarm (through AlarmManager) that checks for new data and reset the alarm. (This is so that if the user disables the alarm it is cancelled before the next time he/she reboots.)

3) Start the AsyncTask. If the app was launched from the notification, pass in a little bit of the data and then cancel the notification.

I’m stuck on what could be causing this exception. It seems that the exception is from the AsyncTask code, so I’m not sure how I can fix it.

Thanks!

Here is the exception:

I/My App(  501): doInBackground exiting
W/MessageQueue(  501): Handler{442ba140} sending message to a Handler on a dead thread
W/MessageQueue(  501): java.lang.RuntimeException: Handler{442ba140} sending message to a Handler on a dead thread
W/MessageQueue(  501):  at android.os.MessageQueue.enqueueMessage(MessageQueue.java:179)
W/MessageQueue(  501):  at android.os.Handler.sendMessageAtTime(Handler.java:457)
W/MessageQueue(  501):  at android.os.Handler.sendMessageDelayed(Handler.java:430)
W/MessageQueue(  501):  at android.os.Handler.sendMessage(Handler.java:367)
W/MessageQueue(  501):  at android.os.Message.sendToTarget(Message.java:348)
W/MessageQueue(  501):  at android.os.AsyncTask$3.done(AsyncTask.java:214)
W/MessageQueue(  501):  at java.util.concurrent.FutureTask$Sync.innerSet(FutureTask.java:252)
W/MessageQueue(  501):  at java.util.concurrent.FutureTask.set(FutureTask.java:112)
W/MessageQueue(  501):  at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:310)
W/MessageQueue(  501):  at java.util.concurrent.FutureTask.run(FutureTask.java:137)
W/MessageQueue(  501):  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
W/MessageQueue(  501):  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
W/MessageQueue(  501):  at java.lang.Thread.run(Thread.java:1096)

EDIT: Here is my onCreate method in my main activity (the one opened by the notification). There are some onClickListeners that I omitted to save space. I don’t think they should have any effect, since the buttons they are attached to are not being pressed.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Call the parent

    setContentView(R.layout.main); // Create the UI from the XML file

    // Find the UI elements
    controls = (SlidingDrawer) findViewById(R.id.drawer); // Contains the
    // buttons
    // comic = (ImageView) findViewById(R.id.comic); // Displays the comic
    subtitle = (TextView) findViewById(R.id.subtitleTxt); // Textbox for the
    // subtitle
    prevBtn = (Button) findViewById(R.id.prevBtn); // The previous button
    nextBtn = (Button) findViewById(R.id.nextBtn); // The next button
    randomBtn = (Button) findViewById(R.id.randomBtn); // The random button
    fetchBtn = (Button) findViewById(R.id.comicFetchBtn); // The go to specific id button
    mostRecentBtn = (Button) findViewById(R.id.mostRecentBtn); // The button to go to the most recent comic
    comicNumberEdtTxt = (EditText) findViewById(R.id.comicNumberEdtTxt); // The text box to Zooming image view setup
    zoomControl = new DynamicZoomControl();

    zoomListener = new LongPressZoomListener(this);
    zoomListener.setZoomControl(zoomControl);

    zoomComic = (ImageZoomView) findViewById(R.id.zoomComic);
    zoomComic.setZoomState(zoomControl.getZoomState());
    zoomComic.setImage(BitmapFactory.decodeResource(getResources(), R.drawable.defaultlogo));
    zoomComic.setOnTouchListener(zoomListener);

    zoomControl.setAspectQuotient(zoomComic.getAspectQuotient());

    resetZoomState();

    // enter the new id
    imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // Used to hide the soft keyboard

    Log.i(LOG_TAG, "beginning loading of first comic");
    int notificationComicNumber = getIntent().getIntExtra("comic", -1);
    Log.i(LOG_TAG, "comic number from intent: " + notificationComicNumber);
    if (notificationComicNumber == -1) {
        fetch = new MyFetcher(this, zoomComic, subtitle, controls, comicNumberEdtTxt, imm, zoomControl);
        fetch.execute(MyFetcher.LAST_DISPLAYED_COMIC);
    } else {
        fetch = new MyFetcher(this, zoomComic, subtitle, controls, comicNumberEdtTxt, imm, zoomControl);
        fetch.execute(notificationComicNumber);
        ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).cancelAll();
    }
    Log.i(LOG_TAG, "ending loading of new comic");

    Log.i(LOG_TAG, "first run checks beginning");
    // Get SharedPreferences
    prefs = getSharedPreferences("prefs", Context.MODE_PRIVATE);

    // Check if this is the first run of the app for this version
    if (prefs.getBoolean("firstRun-" + MAJOR_VERSION_NUMBER, true)) {
        prefs.edit().putBoolean("firstRun-" + MAJOR_VERSION_NUMBER, false).commit();
        firstRunVersionDialog();
    }

    // Check if this is the first run of the app
    if (prefs.getBoolean("firstRun", true)) {
        prefs.edit().putBoolean("firstRun", false).commit();
        firstRunDialog();
    }
    Log.i(LOG_TAG, "First run checks done");

            // OnClickListener s for the buttons omitted to save space

EDIT 2: I’ve been digging through Android source code tracking down where the exception is coming from. This is lines 456 and 457 of sendMessageAtTime in Handler:

msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);

And this is enqueueMessage from MessageQueue:

    final boolean enqueueMessage(Message msg, long when) {
        if (msg.when != 0) {
            throw new AndroidRuntimeException(msg
                    + " This message is already in use.");
        }
        if (msg.target == null && !mQuitAllowed) {
            throw new RuntimeException("Main thread not allowed to quit");
        }
        synchronized (this) {
            if (mQuiting) {
                RuntimeException e = new RuntimeException(
                    msg.target + " sending message to a Handler on a dead thread");
                Log.w("MessageQueue", e.getMessage(), e);
                return false;
            } else if (msg.target == null) {
                mQuiting = true;
            }

            msg.when = when;
            //Log.d("MessageQueue", "Enqueing: " + msg);
            Message p = mMessages;
            if (p == null || when == 0 || when < p.when) {
                msg.next = p;
                mMessages = msg;
                this.notify();
            } else {
                Message prev = null;
                while (p != null && p.when <= when) {
                    prev = p;
                    p = p.next;
                }
                msg.next = prev.next;
                prev.next = msg;
                this.notify();
            }
        }
        return true;
    }

I’m a little confused about what mQuiting is, but it looks like the previous time enqueueMessage was called msg.target was null.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T12:46:26+00:00Added an answer on May 31, 2026 at 12:46 pm

    To generalize Jonathan Perlow’s solution to the bug he identified specifically, I use the following in any class that uses AsyncTask. The looper/handler/post is how you can run something on the UI thread anywhere in an Android app without passing down a handle to an activity or other context. Add this static initialization block inside the class:

    { // https://stackoverflow.com/questions/4280330/onpostexecute-not-being-called-in-asynctask-handler-runtime-exception
        Looper looper = Looper.getMainLooper();
        Handler handler = new Handler(looper);
        handler.post(new Runnable() {
          public void run() {
            try {
              Class.forName("android.os.AsyncTask");
            } catch (ClassNotFoundException e) {
              e.printStackTrace();
            }
          }
        });
    }
    

    We had run into the problem when trying to get unit tests to run. I found a workaround for that, but hadn’t specifically identified the problem. We only knew that trying to use AsyncTask<> in Android JUnit test caused onPostExecute() not to be called. Now we know why.

    This post shows how to run multithreaded async code in an Android JUnit test:

    Using CountDownLatch in Android AsyncTask-based JUnit tests

    For use with non-UI unit tests, I created a simple subclass of android.test.InstrumentationTestCase. It has an “ok” flag and a CountDownLatch. reset() or reset(count) creates a new CountDownLatch({1,count}). good() sets ok=true, count–, and calls.countDown() on the latch. bad() sets ok=false, and counts down all the way. waitForIt(seconds) waits for timeout or the coundown latch to zero. Then it calls assertTrue(ok).

    Then tests are like:

    someTest() {
      reset();
      asyncCall(args, new someListener() {
        public void success(args) { good(); }
        public void fail(args) { bad(); }
      });
      waitForIt();
    }
    

    Because of the AsyncTask static initialization bug, we had to run our actual tests inside a Runnable passed to runTestOnUiThread(). With proper static initialization as above, this shouldn’t be necessary, unless the call being tested needs to run on the UI thread.

    The other idiom I now use is to test whether the current thread is the UI thread and then run the requested action on the proper thread regardless. Sometimes, it makes sense to allow the caller to request sync vs. async, overriding when necessary. For instance, network requests should always be run on a background thread. In most cases, AsyncTask thread pooling is perfect for this. Just realize that only a certain number will run at once, blocking additional requests. To test whether the current thread is the UI thread:

    boolean onUiThread = Looper.getMainLooper().getThread() == Thread.currentThread();
    

    Then use a simple subclass (just doInBackground() and onPostExecute() are needed) of AsyncTask<> to run on a non-UI thread or handler.post() or postDelayed() to run on the UI thread.

    Giving the caller the option to run sync or async looks like (getting a locally valid onUiThread value not shown here; add local booleans as above):

    void method(final args, sync, listener, callbakOnUi) {
      Runnable run = new Runnable() { public void run() {
        // method's code... using args or class members.
        if (listener != null) listener(results);
        // Or, if the calling code expects listener to run on the UI thread:
        if (callbackOnUi && !onUiThread)
          handler.post(new Runnable() { public void run() {listener()}});
        else listener();
      };
      if (sync) run.run(); else new MyAsync().execute(run);
      // Or for networking code:
      if (sync && !onUiThread) run.run(); else new MyAsync().execute(run);
      // Or, for something that has to be run on the UI thread:
      if (sync && onUiThread) run.run() else handler.post(run);
    }
    

    Also, using AsyncTask can be made very simple and concise. Use the definition of RunAsyncTask.java below, then write code like this:

        RunAsyncTask rat = new RunAsyncTask("");
        rat.execute(new Runnable() { public void run() {
            doSomethingInBackground();
            post(new Runnable() { public void run() { somethingOnUIThread(); }});
            postDelayed(new Runnable() { public void run() { somethingOnUIThreadInABit(); }}, 100);
        }});
    

    Or simply:new RunAsyncTask(“”).execute(new Runnable(){public void run(){ doSomethingInBackground(); }});

    RunAsyncTask.java:

    package st.sdw;
    import android.os.AsyncTask;
    import android.util.Log;
    import android.os.Debug;
    
    public class RunAsyncTask extends AsyncTask<Runnable, String, Long> {
        String TAG = "RunAsyncTask";
        Object context = null;
        boolean isDebug = false;
        public RunAsyncTask(Object context, String tag, boolean debug) {
          this.context = context;
          TAG = tag;
          isDebug = debug;
        }
        protected Long doInBackground(Runnable... runs) {
          Long result = 0L;
          long start = System.currentTimeMillis();
          for (Runnable run : runs) {
            run.run();
          }
          return System.currentTimeMillis() - start;
        }
        protected void onProgressUpdate(String... values) {        }
        protected void onPostExecute(Long time) {
          if (isDebug && time > 1) Log.d(TAG, "RunAsyncTask ran in:" + time + " ms");
          v = null;
        }
        protected void onPreExecute() {        }
        /** Walk heap, reliably triggering crash on native heap corruption.  Call as needed. */  
        public static void memoryProbe() {
          System.gc();
          Runtime runtime = Runtime.getRuntime();
          Double allocated = new Double(Debug.getNativeHeapAllocatedSize()) / 1048576.0;
          Double available = new Double(Debug.getNativeHeapSize()) / 1048576.0;
          Double free = new Double(Debug.getNativeHeapFreeSize()) / 1048576.0;
          long maxMemory = runtime.maxMemory();
          long totalMemory = runtime.totalMemory();
          long freeMemory = runtime.freeMemory();
         }
     }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

In my project I have a AsyncTask that fetches some JSON data from the
I have an asynctask that reads data from a device and then I want
I have custom AsyncTask (ListDownloadTask) that download data and updates UI. I want to
Have the following asynctask that i'm using to download some images. Works fine except
I have created an AsyncTask that loads data from a website then when I
I have a class that extends AsyncTask , which fetches the gps cordinates from
I have an Activity class which has an attribute that references an AsyncTask instance
I have a class that fetches data in response to button presses in the
I have an AsyncTask that queries a content provider and does some additional processing
I have AsyncTask that processes some background HTTP stuff. AsyncTask runs on schedule (Alarms/service)

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.