1

I have a queue of Jobs which execute sequentially - the onRun() of each job looks like this:

    @Override
    public void onRun() throws Throwable {
        if (Looper.myLooper() == null) {
            Looper.prepare();
        }
        this.looper = Looper.myLooper();
        makeQuery(looper);
        Looper.loop();
    }

the makeQuery() function does a database call that runs on a background thread that reports back to this job by posting a Runnable to a handler for this thread. Like so:

{
    // ... make a query in another thread...
    Handler handler = new Handler(looper);
    handler.post(new Runnable() {...});
}

And when the result of the query is received, it does something then calls:

this.looper.quit();

So far so good - the first job on the queue executes fine, but the 2nd job gets as far as executing the query and then the code above that tries to post the result - handler.post - fails with this exception:

"sending message to a Handler on a dead thread"

One thing I noticed is that the 2nd job is running on the same thread as the first, so the JobManager is reusing it, given that it has been configured for FIFO operation, I guess that is efficient. However, why is the thread in the state 'Quitting' when the second job runs on it that is causing this process to barf?

Blackbelt
  • 156,034
  • 29
  • 297
  • 305
  • 1
    This isn't how one uses Looper. It is unusable until you call Looper.loop, and once you did, handling messages is the only thing the thread will ever do. Looks like you are better off using Scheduler subclasses instead. – user1643723 Jul 10 '15 at 08:00
  • Why are you doing it this way as a matter of interest? Wouldn't using an `AsyncTask` be more suitable for your purpose? – kha Jul 10 '15 at 08:19
  • so you wana build your own HandlerThread ? – Selvin Jul 10 '15 at 08:42
  • I have a FIFO queue of jobs where each is a state machine that must respond to various async events before they are done, hence the job's onRun() needs to wait on something. So the job starts - job manager calls onRun(). The job initiates a process and waits at Looper.loop(). Sometime later an event happens that signals the job should end - it does so by posting a runnable to the Handler of the Job's thread. In that Runnable, it calls Looper quit, completing the job thread, and the next job to start. This works for the 1st job, but when the 2nd job Runnable is posted , it gets the error. – user3769865 Jul 12 '15 at 23:18
  • OK, to further this, it seems that the JobManager is using the same thread to execute the 2nd Job. At the point where the second Job is ready to wait at loop() I examined the message queue associated with the looper, and it already has 'mQuitting'=true. So when the Job completes and a message is posted to the Handler, it fires the exception. Question is, why is it quitting? Is it still in the process of quitting from the first Job when the second is run ? – user3769865 Jul 13 '15 at 01:59
  • So this is the same problem I am having. It says you can only call looper.quit() once? I guess I dont care that much but it puts me in a bind because the JobManager insists on using the same thread in such a way that subsequent jobs dont get a new Looper... http://stackoverflow.com/questions/3643006/calling-looper-more-than-once-causes-sending-message-to-a-handler-on-a-dead-thr – user3769865 Jul 13 '15 at 02:45

0 Answers0