0

I use a bound service to run cpu-intensive tasks in the background as recommended to avoid ANR. The client application sends messages to the bound service that handles them in the handleMessage() method of its Handler.

As some requests can take very long to answer, I want to offer the user the ability to "abort/abandon" a running request. However, I can not destroy the service because I need to keep its context for future requests. Sending an "abort" request from the application will be queued and handled by the service after it will have completed its current task, which is obviously too late and not implementing the requested functionality.

Is there a way for the client application to kill a running request without killing the service and losing its associated context?

* EDIT * Thanks to Mario's recommendation and this link, here is the solution I have implemented:

    ExecutorService executor = Executors.newFixedThreadPool(1);
    private volatile static Future<?> BackgroundSolveFuture = null;

    public class IncomingHandler extends Handler {

    @Override
    public void handleMessage(Message message) {
        msg = message;
        msgArg1 = message.arg1;
        msgWhat = message.what;

        if (message.replyTo != null) {
            mClient = new Messenger(message.replyTo.getBinder());
        }

        switch (msgWhat) {
            case MSG_ABORT:
                BackgroundSolveFuture = null;
                break;
            case MSG_SOLVE:case MSG_ANALYZE:case MSG_SUGGEST:case MSG_STEP:
                BackgroundSolveFuture = executor.submit(new Runnable() {
                    public void run() {
                        solve();
                    }
                });
                break;
            ...

Inside solve() I regularly check whether BackgroundSolveFuture has been set to null:

        if (BackgroundSolveFuture == null) {
            undoAction(true);
            return;
        }
ema3272
  • 1,021
  • 2
  • 13
  • 28

1 Answers1

1

yes.

your idea with sending abort message is ok.

you just need create new thread for each task. For example you have two types of messages DOIT and ABORT, when you get message DOIT you create and run new thread with task, you can even keep reference to this thread.

This allows finish quickly a handleMessage() method.

Then new message come: ABORT, you have reference to thread and you can interrupt the thread/task.

mariopce
  • 1,116
  • 9
  • 17